In screen development with Spring Boot + Thymeleaf, I want to customize the error screen to be displayed according to the status code (4xx, 5xx, etc.) when some error occurs.
Spring Boot Version 2.1.3.RELEASE
BasicErrorController For screen development with Spring Boot + Thymeleaf, an endpoint is prepared for when an error occurs. The controller class that becomes the endpoint is as follows.
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.java
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
As described in @RequestMapping ("$ {server.error.path: $ {error.path: / error}} ")
, in application.yaml (properties), set "server.error.path" to the error screen. If you describe the URL, that URL will be the endpoint. If not set, "/ error" will be the endpoint by default (as described in $ {error.path: / error}).
Therefore, even if the developer does not create an error controller, the error screen can be displayed simply by arranging the error screen HTML in the following configuration.
※http://localhost:8080/error -> 5xx.html
※http://localhost:8080/error/404 -> 4xx.html
However, in this case, the prepared error HTML is static, so for example, "take out the login information from the session and display it in the error screen header and footer" "take out a certain value from the DB and XXX it to the error screen There are also requests for dynamic customization, such as "display in."
In such a case, try expanding it as follows. In BasicErrorController # resolveErrorView (request, response, status, model), resolveErrorView of parent class AbstractErrorController is called, and resolveErrorView of ErrorResolver is called in resolver.resolveErrorView (request, status, model) in it. Since the resolver uses "org.springframework.boot.autoconfigure.web.servlet.errorDefaultErrorViewResolver" by default, create a Resolver (named CustomeErrorViewResolver here) that extends this class, and override the resolveErrorView method there. Create a dynamically customized ModelAndView and return. This alone enables dynamic customization.
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.java
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController.java
protected ModelAndView resolveErrorView(HttpServletRequest request,
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
for (ErrorViewResolver resolver : this.errorViewResolvers) {
ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
if (modelAndView != null) {
return modelAndView;
}
}
return null;
}
The following image.
CustomeErrorViewResolver.java
@Component
public class CustomeErrorViewResolver extends DefaultErrorViewResolver {
/**
* Create a new {@link DefaultErrorViewResolver} instance.
* @param applicationContext the source application context
* @param resourceProperties resource properties
*/
public CustomeErrorViewResolver(ApplicationContext applicationContext,ResourceProperties resourceProperties) {
super(applicationContext, resourceProperties);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
final ModelAndView mav = super.resolveErrorView(request, status, model);
if (status.is4xxClientError()) {
//Processing at the time of 4XX system error
} else if (status.is5xxServerError()) {
//Processing at the time of 5XX system error
}
return mav;
}
}
that's all.
Recommended Posts