写于:2020-02-10 05:50:37

在项目中,存在需求需要统一对代码进行做拦截处理,比如:日志记录,xss处理,全局异常处理等。实现拦截功能的方式也很多,可以通过 Filter、HandlerInterceptor、ControllerAdvice、Aop 来实现。 所以了解这些实现方式之间的执行顺序,对于开发来说变得至关重要。

# 分析以上几种拦截功能的执行顺序

来看一张各拦截器执行的平面剖析图

Filter、HandlerInterceptor、ControllerAdvice、Aop执行顺序_图示

从图中能够得出集中拦截器同时存在时各自的执行顺序,包括多个同种类型拦截器存在时各自的执行顺序。

# 从源码层面分析各种拦截器执行顺序

在 Filter、HandlerInterceptor、ControllerAdvice、Aop 中除了 Filter 外其他的都是 Spring MVC 模块中的功能。

在 Spring MVC 中,所有请求的入口为 DispatcherServlet,而 DispatcherServlet 本身是一个 Servlet 。而 Filter 是对 Servlet 进行拦截的过滤器, 所以在这几种拦截器实现方式中 Filter 是最先被执行的。

下面通过 DispatcherServlet 源码分析各种拦截器的执行顺序

DispatcherServlet 本身就是一个Servlet ,Servlet 在处理 Request 时会调用 Servlet#service 。在 DispatcherServlet 中 DispatcherServlet#doService 会调用 DispatcherServlet#doDispatch 。

public class DispatcherServlet extends FrameworkServlet {
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	try {
	        // 执行 HandlerInterceptor#preHandler
	        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
	            return;
	        }

	        // 执行 AOP + controller 方法
	        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

	        // 执行 HandlerInterceptor#postHandle
	        mappedHandler.applyPostHandle(processedRequest, response, mv);

	        // 执行 ControllerAdvice 异常处理代码
	        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	    }
	    catch (Exception ex) {
	    	// 执行 HandlerInterceptor#afterCompletion 
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
    }
}

以上源码的简单剖析能够验证,几种拦截器共存时各自的执行顺序.

# 代码验证拦截器执行顺序

# 多个 Filter 代码

案例_Filter代码

# 多个 HnadlerInterceptor 代码

案例_HandlerInterceptor代码

# 多个 ControllerAdvice 代码

案例_HandlerInterceptor代码

# 多个 AOP 的执行顺序 代码

案例_HandlerInterceptor代码

# 测试用的 API 代码

案例_HandlerInterceptor代码

# 测试打印日志

程序正常运行时

案例_HandlerInterceptor代码

程序抛出异常时

案例_HandlerInterceptor代码

# 同种拦截器的执行顺序

# Filter

多个 Filter 的执行顺序在其注册时候可以指定。值越小,优先级越高。

案例如下图:

多个Filter执行顺序配置案例

# HandlerInterceptor

多个 HandlerInterceptor ,各自的执行顺序根据在 WebMvcConfigurer#addInterceptors 设置拦截器时,先进先出,先设置的优先级高。

案例如下图:

多个Filter执行顺序配置案例

# ControllerAdvice

结合异常处理,多个 ControllerAdvice 哪个匹配到,就那个进行处理。

# AOP

多个 AOP 通过 @Order 注解进行优先级设置,数值越小越优先

AOP执行顺序配置案例

精彩内容推送,请关注公众号!
最近更新时间: 4/6/2020, 2:52:03 PM