层层递进的关系来分析 SpringBoot 的Web模块源码
1. SpringBoot Web源码分析(一) 静态资源源码分析
2. SpringBoot Web源码分析(二) 请求处理源码分析
3. SpringBoot Web源码分析(三) 响应处理源码分析
4. SpringBoot Web源码分析(四) 视图解析器源码分析
5. SpringBoot Web源码分析(五),拦截器和文件上传
6. SpringBoot Web源码分析(六) 异常处理和Servlet组件
7. SpringBoot Web源码分析(七) 嵌入式服务器和定制化原理
文章目录
1.7 异常处理
1.7.1 错误处理
1. 默认规则
-
默认情况下,Spring Boot提供/error处理所有错误的映射
-
对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
-
要对其进行自定义,添加View解析为error
-
要完全替换默认行为,可以实现 ErrorController 并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。
-
error/下的4xx,5xx页面会被自动解析;
2. 定制错误处理逻辑
- 自定义错误页
- @ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
- @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
- Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
3. 异常处理自动配置原理
-
ErrorMvcAutoConfiguration 自动配置异常处理规则
这里的ServerProperties.class 和 WebMvcProperties.class 中定义了许多配置属性- 容器中的组件:DefaultErrorAttribute( id:errorAttribute)
- DefaultErrorAttributes:定义错误页面中可以包含哪些数据。
- DefaultErrorAttributes:定义错误页面中可以包含哪些数据。
- 容器中的组件:DefaultErrorAttribute( id:errorAttribute)
-
public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver**
-
容器中的组件:类型:BasicErrorController (id:basicErrorController)json+白页 适配响应
-
默认处理 /error 路径的请求
- 容器中有组件 View->id是error;(响应默认错误页)
- 容器中放组件 BeanNameViewResolver(视图解析器);按照返回的视图名作为组件的id去容器中找View对象。-
容器中的组件:类型:DefaultErrorViewResolver -> id:conventionErrorViewResolver
- 如果发生错误,会以HTTP的状态码 作为视图页地址(viewName),找到真正的页面
- error/404、5xx.html
如果想要返回页面;就会找error视图【StaticView】。(默认是一个白页)
-
4.总结:异常处理步骤流程
- 执行目标方法,目标方法运行期间有任何异常都会被catch、而且标志当前请求结束;并且用 dispatchException
- 进入视图解析流程(页面渲染)
rocessDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
- mv = processHandlerException;处理handler发生的异常,处理完成返回ModelAndView;
- 遍历所有的 handlerExceptionResolvers,看谁能处理当前异常【HandlerExceptionResolver处理器异常解析器】
- 系统默认的 异常解析器;
-
DefaultErrorAttributes先来处理异常。把异常信息保存到rrequest域,并且返回null;
-
默认没有任何人能处理异常,所以异常会被抛出
- 如果没有任何人能处理最终底层就会发送 /error 请求。会被底层的BasicErrorController处理
- 解析错误视图;遍历所有的 ErrorViewResolver 看谁能解析。
- 默认的 DefaultErrorViewResolver ,作用是把响应状态码作为错误页的地址,error/500.html
- 模板引擎最终响应这个页面 error/500.html
-
1.8 Web原生组件注入(Servlet、Filter、Listener)
1.8.1 基本步骤
1. 使用 Servlet API
Servlet
@ServletComponentScan(basePackages = "")
@WebServlet("")
注意:这种方式不会走 SpringMVC 的拦截器
Filter
@ServletComponentScan(basePackages = "")
@WebFilter(urlPatterns ={""})
Listener
@ServletComponentScan(basePackages = "")
@WebListener
2. RegistrationBean 方式
ServletRegistrationBean, FilterRegistrationBean, ServletListenerRegistrationBean
@Configuration
public class MyRegistConfig {
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter = new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
return new ServletListenerRegistrationBean(mySwervletContextListener);
}
}
1.8.2 分析:DispatchServlet 如何注册进来
● 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。
● 通过 ServletRegistrationBean 把 DispatcherServlet 配置进来。
● 默认映射的是 / 路径。
多个Servlet都能处理到同一层路径,精确优选原则