thymeleaf设置自定义错误处理页面404,500等

thymeleaf设置自定义错误处理页面404,500等

springboot默认错误处理机制

1)浏览器,返回一个默认的错误界面

thymeleaf设置自定义错误处理页面404,500等

2)其他客户端默认相应一个json数据

thymeleaf设置自定义错误处理页面404,500等

观察源码:

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
@RequestMapping(produces = "text/html")//产生html类型的数据,浏览器发送的请求来到这个方法处理
    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 ? new ModelAndView("error", model) : modelAndView);
    }
​
    @RequestMapping
    @ResponseBody//产生json数据,其他客户端来到这个方法处理
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }
    private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
​
        private final ServerProperties properties;
​
        protected ErrorPageCustomizer(ServerProperties properties) {
            this.properties = properties;
        }
​
        @Override
        public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
            ErrorPage errorPage = new ErrorPage(this.properties.getServletPrefix()
                    + this.properties.getError().getPath());
            errorPageRegistry.addErrorPages(errorPage);
        }
​
        @Override
        public int getOrder() {
            return 0;
        }
​
    }
    @Configuration
    static class DefaultErrorViewResolverConfiguration {
​
        private final ApplicationContext applicationContext;
​
        private final ResourceProperties resourceProperties;
​
        DefaultErrorViewResolverConfiguration(ApplicationContext applicationContext,
                ResourceProperties resourceProperties) {
            this.applicationContext = applicationContext;
            this.resourceProperties = resourceProperties;
        }
​
        @Bean
        @ConditionalOnBean(DispatcherServlet.class)
        @ConditionalOnMissingBean
        public DefaultErrorViewResolver conventionErrorViewResolver() {
            return new DefaultErrorViewResolver(this.applicationContext,
                    this.resourceProperties);
        }
​
    }

因为代码和老师讲的不太一样,但是这几个类随便点点就大概知道了

一旦出现4xx或者5xx之类的错误,ErrorPageCustomizer就会生效(定制错误界面的显示规则);就会发送来到/error请求;就会被BasicErrorContrller处理

响应去哪个界面是由DefaultErrorViewResolver决定的

​
        @Bean
        @ConditionalOnBean(DispatcherServlet.class)
        @ConditionalOnMissingBean
        public DefaultErrorViewResolver conventionErrorViewResolver() {
            return new DefaultErrorViewResolver(this.applicationContext,
                    this.resourceProperties);
        }

 

如何自定义Error界面)

1)在templates目录下面添加error目录

2)添加404.html,500.html,4xx.html优先匹配最合适的

 

 

默认拥有的数据:

timestamp

status

error

message

path

在前台显示:

    <h1>status:[[${status}]]</h1>
    <h2>timestamp:[[${timestamp}]]</h2>

添加自定义信息:

创建自定义异常处理器

@ControllerAdvice//成为异常处理器
public class MyExceptionHandler {
​
    //1、浏览器客户端返回的都是json:没有自适应
//    @ResponseBody
//    @ExceptionHandler(UserNotExistException.class)//Exception.class处理全部异常
//    public Map<String,Object> handleException(Exception e){
//        Map<String,Object> map = new HashMap<>();
//        map.put("code","user.notexist");
//        map.put("message",e.getMessage());
//        return map;
//    }
​
    //2.有自适应
    //我们处理返回得到的json,其他客户端得到的是网页
    @ExceptionHandler(UserNotExistException.class)//要处理的异常
    public String handleException(Exception e, HttpServletRequest request){//加上HttpServletRequest传入状态码
        Map<String,Object> map = new HashMap<>();
        //传入我们自己的错误状态码  4xx 5xx
        /**
         * Integer statusCode = (Integer) request
         .getAttribute("javax.servlet.error.status_code");
         */
        request.setAttribute("javax.servlet.error.status_code",500);//设置状态码
        map.put("code","user.notexist");
        map.put("message","用户出错啦");
​
        request.setAttribute("ext",map);//将自己定制数据携带到错误界面
        //转发到/error
        return "forward:/error";
    }
}
​

自定义错误界面不生效:

查看error文件夹是否在templates目录下

发现一个写的很细的关于这个的https://www.jianshu.com/p/be27d6288a67