Spring Загрузочная и пользовательская страница ошибок 404

В моем приложении Spring Boot я пытаюсь настроить пользовательские страницы ошибок, например, для 404, я добавил следующий компонент в конфигурацию своего приложения:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
        }
    };
}

Кроме того, я создал следующий простой шаблон Thymeleaf:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>404 Not Found</title>
        <meta charset="utf-8" />
    </head>
    <body>
        <h3>404 Not Found</h3>
        <h1 th:text="${errorCode}">404</h1>
        <p th:utext="${errorMessage}">Error java.lang.NullPointerException</p>
        <a href="/" th:href="@{/}">Back to Home Page</a>
    </body>
</html>

и добавил его в папку /resources/templates/. Прямо сейчас на ошибке 404 я вижу только белый экран.

Что я делаю не так и как правильно настроить мою страницу 404? Кроме того, возможно ли использовать шаблоны, а не только статические страницы для пользовательских страниц ошибок?

Ответы

Ответ 1

В Spring Boot 1.4.x вы можете добавить страницу пользовательских ошибок:

Если вы хотите отобразить страницу пользовательской HTML-ошибки для данного кода состояния, вы добавляете файл в папку /error. Страницы ошибок могут быть статическими HTML (то есть добавлены в любую из статических каталогов ресурсов) или созданы с использованием шаблонов. Имя файла должно быть точным кодом состояния или маской серии.

Например, чтобы сопоставить 404 с статическим HTML файлом, ваша структура папок будет выглядеть так:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

Ответ 2

Вы используете Thymeleaf, а Thymeleaf может обрабатывать ошибки без контроллера.

Для общей страницы ошибок эту страницу Thymeleaf нужно назвать как error.html
и должен быть помещен в src/main/resources > templates > error.html

Thymleaf error.html

Для определенных страниц ошибок вам необходимо создать файлы с именем http-кода ошибки в папке с именем error, например: src/main/resources/templates/error/404.html.

Ответ 3

new ErrorPage (HttpStatus.NOT_FOUND, "/404.html" )

Этот /404.html представляет URL-путь для перенаправления, а не имя шаблона. Поскольку вы настаиваете на использовании шаблона, вы должны создать контроллер, который обрабатывает /404.html и отображает ваш 404.html в src/main/resources/templates:

@Controller
public class NotFoundController {
    @RequestMapping("/404.html")
    public String render404(Model model) {
        // Add model attributes
        return "404";
    }
}

Вы также можете заменить эти только просмотр контроллеров рендеринга-рендера контроллером вида:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/404.html").setViewName("404");
    }
}

Кроме того, можно ли использовать шаблоны, а не только статические страницы для пользовательские страницы ошибок?

Да, это возможно. Но не найденные страницы, как правило, статичны, и использование шаблона вместо обычных HTML-страниц не будет иметь большого смысла.

Ответ 4

Нет необходимости в EmbeddedServletContainerCustomizer bean. Простое размещение соответствующей страницы ошибки (например, 404.html в случае 404) в общедоступном каталоге должно быть достаточно (как указано @brunoid).

Также обратите внимание, что вы также можете поместить общую страницу error.html, которая будет отображаться всякий раз, когда ваше приложение сталкивается с ошибкой или исключением.

Простой пример (во Фримаркере) -

<html lang="en">
<head>
</head>
<body>
    <div class="container">
        <div class="jumbotron alert-danger">
            <h1>Oops. Something went wrong</h1>
            <h2>${status} ${error}</h2>
        </div>
    </div>
</body>

</html>

Это отобразит надлежащее состояние ошибки и соответствующее сообщение об ошибке. И поскольку вы используете Spring Boot, вы всегда можете отменить сообщения о статусе и ошибках, отображаемые на странице ошибок.

Ответ 5

Если вы используете Thymeleaf, как предлагается в вопросе, вы можете использовать шаблон, аналогичный шаблону из предыдущего ответа, но подходящий для Thymeleaf, а не для Freemarker. Я также добавил бутстрап для стилизации:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
<title>Error Page</title>
<link href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" rel="stylesheet" media="screen"/>
<script src="/webjars/jquery/3.2.1/jquery.min.js"></script>
<script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="jumbotron alert-danger">
    <h1>Oops... something went wrong.</h1>
    <h2 th:text="${status + ' ' + error}"></h2>
</div>
</div>
</body>
</html>

Вы должны поместить этот код в файл с именем error.html и поместить его в каталог шаблонов thymeleaf. Нет необходимости добавлять дополнительный контроллер для работы.

Ответ 6

Thymeleaf может обрабатывать ошибку без контроллера. создайте папку errors.html в ресурсах.

Ответ 7

Мы должны добавить новый

 @Controller
public class MyErrorController implements ErrorController  {

    @RequestMapping("/error")
public String handleError(HttpServletRequest request) {
    Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

    if (status != null) {
        Integer statusCode = Integer.valueOf(status.toString());

        if(statusCode == HttpStatus.NOT_FOUND.value()) {
            return "error404";
        }
        else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
            return "error500";
        }
    }
    return "error";
}

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

Ответ 8

Проверьте, есть ли у вас в списке путей тимили, или добавьте приведенный ниже код и повторно импортируйте проект.

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>