介绍 从浏览器发送出的请求,服务器的处理流程.
本文针对 springboot 应用。
总览
1 2
| 浏览器请求 -> filter过滤器 -> Interceptor拦截器 -> ControllerAdvice -> Aspect 切片 -> Controller 浏览器请求 <- filter过滤器 <- Interceptor拦截器 <- ControllerAdvice <- Aspect 切片 <- Controller
|
4种方式对比:
- Filter: Servlet 规定的组件。只能处理 ServletRequest 和 ServletResponse。
- Interceptor: Spring 自己实现的。不仅能处理 HttpServletRequest和HttpServletResponse,还能获取 对应的Controller方法 。
- ControllerAdvice: 通常用来做 统一异常处理
- Aspect: 自定义要切入的类或者方法。粒度最小。
filter过滤器
filter过滤器 属于 Servlet 规则中的组件。
最重要的方法是 doFilter()。
下面的代码简单展示了 ApplicationFilterChain 的处理过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public final class ApplicationFilterChain implements FilterChain { public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (Globals.IS_SECURITY_ENABLED) { } else { this.internalDoFilter(request, response); } }
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (this.pos < this.n) { } else { } } }
|
流程为:
1 2
| 浏览器 -> ApplicationFilterChain -> DispatcherServlet 浏览器 <- ApplicationFilterChain <- DispatcherServlet
|
Interceptor 拦截器
Interceptor 拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,
也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。
拦截器 的优点:
- 持有 HttpServletRequest
- 持有 HttpServletResponse
- 持有一个 handler: 包含了 Controller 实例、处理请求的方法和参数等信息
拦截器接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; }
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { }
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
|
spring 拦截器的生效代码在 DispatcherServlet 和 HandlerExecutionChain中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class DispatcherServlet extends FrameworkServlet { protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { try { try { try { if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Throwable var21) { } } catch (Throwable var23) { } } finally { } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class HandlerExecutionChain { boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; } void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = interceptors.length - 1; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } } void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = this.interceptorIndex; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable var8) { logger.error("HandlerInterceptor.afterCompletion threw exception", var8); } } } } }
|
流程为:
1 2
| DispatcherServlet -> HandlerExecutionChain -> HandlerInterceptor DispatcherServlet <- HandlerExecutionChain <- HandlerInterceptor
|
ControllerAdvice
ControllerAdvice 是 controller的增强。可以 与 (ModelAttribute、InitBinder和 ExceptionHandler 配合)。
最常用的组合是 ControllerAdvice 和 ExceptionHandler。用于Controller 异常处理:
1 2 3 4 5 6 7 8 9 10 11
| @ControllerAdvice public class ControllerAdviceTest { @ExceptionHandler(CustomException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public @ResponseBody HashMap<String, Object> handleCustomException(Exception e) { logger.error(e.getMessage(), e); return genErrorMap(e); } }
|
@ExceptionHandler 流程为:
请求来到 DispatcherServlet 中后,经过 具体的Controller 处理后,返回的结果如出现异常。 返回结果会依次经过 DispatcherServlet.processDispatchResult()
和DispatcherServlet.processHandlerException()
。
过程如下:
1 2
| DispatcherServlet.processDispatchResult() -> DispatcherServlet.processHandlerException() -> HandlerExceptionResolver -> ExceptionHandlerExceptionResolver DispatcherServlet.processDispatchResult() <- DispatcherServlet.processHandlerException() <- HandlerExceptionResolver <- ExceptionHandlerExceptionResolver
|
HandlerExceptionResolver 的具体介绍自行查询。
aspect 切片
详见 面向切面编程。