在Spring Boot中对于异常的处理,提供了非常简单的方式,比如说上篇讲的@ControllerAdvice方式的全局异常处理,那是属于SpringMVC中的,如果使用的SSM想做全局异常处理就是用它。如果用的是Spring Boot就可以不需要用它了。
比如说创建一个错误的接口,该接口一运行必定会报错:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
int i=1/0;
return "hello";
}
}
错误页面如下
以上是一个默认的错误页面,我们也可以自定义异常页面,自定义的异常页面分为两种,一种是静态的,一种是动态的。
静态异常页面
静态异常页面时使用HTTP响应码来命名页面,例如一种是400.html,404.html,500.html…等等,另一种是直接定义一个4xx.html,表示400-499的状态都显示这个异常页面,5xx.html表示500-599的状态都显示这个异常页面。
默认是在classpath:/static/error/路径下定义相关页面:
这样以后发生了404的错误就会自动找到404.html页面,发生了500错误就会自动找到500.html页面
这种是静态页面,这样挨个,枚举显然特别麻烦,所以提供了另外一种写法直接定义一个4xx.html,表示400-499的状态都显示这个异常页面,5xx.html表示500-599的状态都显示这个异常页面。
那么像上面这样,既有4xx又有404,既有5xx又有500,那么当发生异常的时候,它们的优先级是怎样的呢?先找精确的(404,500),再找模糊的(4xx,5xx)。但是如果用模糊的又会有新的问题,因为静态页面,页面的数据无法修改,到底发生什么错误,也无法展示出来,所以还支持另一种,动态的错误页面展示。
动态异常页面
动态异常页面,首先地引入页面模板依赖,这里引入的是Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
动态异常页面的默认路径是:classpath:/templates.error
在这里面定义也一样可以定义成404、500和4xx、5xx
还可以通过动态页面获取相应的错误信息:
那么如果这个时候发生404错误,动态异常页面,静态异常页面都有,优先会找谁呢?执行和的页面顺序如下:
发生了404错误:动态的404.html——静态的404.html——动态的4xx.html——静态的4xx.html
还可以自定义自定义异常信息:
创建一个MyErrorAttribute类,继承自DefaultErrorAttributes,重写getErrorAttributes方法
@Component
public class MyErrorAttribute extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
//注意:此处的map比较特殊,它不是HashMap,它是一个UnmodifiableMap
//所以只能读出它的数据,存储在自己的map中 操作自己的map
Map<String,Object> map2=new HashMap<>();
map2.put("error",map.get("error"));
map2.put("mydata","出错了");
return map2;
}
}
在页面中读取mydata:
自定义的异常信息覆盖了原本的异常信息
还可以自定义视图:
创建一个MyErrorViewResolver,继承自 DefaultErrorViewResolver
@Component
public class MyErrorViewResolver extends DefaultErrorViewResolver {
public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) {
super(applicationContext, resourceProperties);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = new ModelAndView("sp/5xx",model);
return modelAndView;
}
}
然后在templates下创建一个sp文件夹如下:
运行结果如下: