默认规则
1. 默认情况下,springboot提供/error处理所有错误的映射
2. 对于机器客户端,它将生成json响应,其中包含错误,http状态和异常消息的详细信息
- 例如postman发送请求

3. 对于浏览器客户端,响应一个“whitelabel”错误视图,以html格式呈现相同的数据

4. 自定义错误视图解析规则
- 完全替换默认行为,可以实现 errorcontroller 并注册该类型的bean定义,或添加errorattributes类型的组件
定制错误处理逻辑
1. 自定义错误页
- 替换默认的“whitelabel”错误视图,在templates在创建error文件夹,定义404和5xx的视图error/404.html error/5xx.html
- 有精确的错误状态码页面就匹配精确,没有就找4xx.html或者n(错误状态码首数字)xx.html;如果都没有就触发白页

2. 方法一:@exceptionhandler处理异常
- 注解用来定义一个或多个具体的异常类型,发生异常时由此处理
- @controlleradvice+@exceptionhandler处理全局异常
- 底层是 exceptionhandlerexceptionresolver 支持的
/**
* 处理整个web controller的异常
*/
@slf4j
@controlleradvice
public class globalexceptionhandler {
//定义可以处理的异常
@exceptionhandler({arithmeticexception.class,
nullpointerexception.class})
public string handlearithexception(exception e){
log.error("异常是:{}",e);
//返回视图地址,也可以返回modelandview
return "login";
}
}3. 方法二:@responsestatus+自定义异常
- 指定发生异常时的响应状态码,自定义异常类型
- 底层是 responsestatusexceptionresolver
- 把responsestatus注解的信息组装成modelandview返回
- 底层调用 response.senderror(statuscode, resolvedreason);
- tomcat发送的/error
//异常响应状态码+异常原因
@responsestatus(value= httpstatus.forbidden,reason = "用户数量太多")
public class usertoomanyexception extends runtimeexception {
public usertoomanyexception(){
}
public usertoomanyexception(string message){
super(message);
}
}4. spring底层的异常
- 如参数类型转换异常
- defaulthandlerexceptionresolver 处理框架底层的异常
- 解析异常时做了一系列异常类型的判断
- 每个异常处理都会执行response.senderror(.....),tomcat发送/error请求
- 如果还是解析不了,就会响应tomcat的错误页面

5. 方法三:自定义实现 handlerexceptionresolver 处理异常
- @order(value = ordered.highest_precedence) 将优先级设为最高
- 如果不加优先级,默认是排列在自动配置的异常处理器之后,若默认的处理器可以处理异常,故自定义的异常处理器不会生效
- 调用response.senderror(.....),tomcat发送/error请求
//优先级,数字越小优先级越高
@order(value= ordered.highest_precedence)
@component
public class customerhandlerexceptionresolver implements handlerexceptionresolver {
@override
public modelandview resolveexception(httpservletrequest request,
httpservletresponse response,
object handler, exception ex) {
try {
//状态码+异常信息
response.senderror(511,"我喜欢的错误");
} catch (ioexception e) {
e.printstacktrace();
}
return new modelandview();
}
}6. 关于response.senderror()
- 自己调用response.senderror(),请求会被转发给basicerrorcontroller进行处理
- 如果自己没有调用,并且异常没有任何人能够处理,tomact底层会自动调用response.senderror()将请求转发给basicerrorcontroller处理。
- 总之,三种方法最后都会调用senderror()转交给basicerrorcontroller处理,errorviewresolver进行解析,最后会转到一个页面或者返回json数据。
异常处理自动配置原理
- errormvcautoconfiguration 自动配置异常处理规则
1. 绑定配置文件的server 和 spring.mvc

2. 自动添加组件:类型:defaulterrorattributes -> id:errorattributes
- defaulterrorattributes:定义错误页面中可以包含哪些数据
- defaulterrorattributes implements errorattributes,handlerexceptionresolver
- 自定义错误页面属性



3. 自动添加组件:类型:basicerrorcontroller --> id:basicerrorcontroller
- 可以通过basicerrorcontroller 自定义页面跳转逻辑
- 处理默认 /error 路径的请求;页面响应 new modelandview("error", model),
- 要么响应一个html页面,要么响应一个json


- 容器中有组件 view->id是error;(响应默认错误页)


- 容器中放组件 beannameviewresolver(视图解析器);按照返回的视图名作为组件的id去容器中找view对象

4. 自动添加组件:类型:defaulterrorviewresolver -> id:conventionerrorviewresolver
- 如果发生错误,会以http的状态码 作为视图名字(viewname),找到真正的页面
- 比如error/404、5xx.html



异常处理步骤流程
- 举例,执行一个controller方法,除数为0抛出异常
1. dodispatch()中执行controller目标方法
- 目标方法运行期间有任何异常都会被catch、而且标志当前请求结束
- 并且将异常赋值给 dispatchexception
- 即使目标方法发生异常,也执行视图解析流程

2. 处理handler发生的异常,处理完成返回modelandview

- 遍历所有的 handlerexceptionresolvers,看谁能处理当前异常【handlerexceptionresolver处理器异常解析器】
- defaulterrorattributes先来处理异常,把异常信息保存到request域,并且返回null
- 然后交由handlerexceptionresolvercomposite,遍历其中的异常处理器处理,但此例子默认无法处理
- exceptionhandlerexceptionresolver,使用注解@exceptionhandler才能由此解析处理
- responsestatusexceptionhandler,使用注解@responsestatus才能由此解析处理


3. 默认无法处理目标方法异常时,异常会被抛出
- 底层就会发送 /error 请求,会被basicerrorcontroller处理

- 解析错误视图;遍历所有的 errorviewresolver 看谁能解析

4. 模板引擎响应出错误视图
- 默认的 defaulterrorviewresolver ,作用是把响应状态码作为错误页的地址,error/500.html
- 查找顺序:
- '/templates/error/500.html' >
- '/static/error/500.html' >
- '/templates/error/5xx.html' >
- '/static/error/5xx.html'

发表评论