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