thymeleaf设置自定义错误处理页面404,500等
thymeleaf设置自定义错误处理页面404,500等
springboot默认错误处理机制
1)浏览器,返回一个默认的错误界面
2)其他客户端默认相应一个json数据
观察源码:
@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