過濾器、攔截器、AOP切面執行順序的比較
過濾器:基於 Servlet,通過函式回撥方式實現,可以過濾請求和圖片檔案等,每個請求一個過濾器只能過濾一次。
攔截器:基於 java 的反射機制,代理模式實現,只能攔截請求,可以訪問上下文等物件,功能強大,一個請求可多次攔截。
攔截器是 Spring 中AOP的一種實現方法。另一種方法通過 Pointcut、Advice實現
下面具體測試三者執行順序:
第一步:新增過濾器
1、web.xml 中新增 filter 及對映
<filter>
<filter-name>GlobalFilter</filter-name>
<filter-class>com.test.filter.GlobalFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>GlobalFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2、新建過濾器
public class GlobalFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException{
System.out.println("--------------------Filter過濾----------------------");
filterChain.doFilter(request, response);
}
}
第二步:新增攔截器
攔截器有兩種方式實現:註解和配置檔案,習慣採用配置檔案方式
1、新增配置,裝配 bean
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.test.interceptor.GlobalInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
2、新建攔截器
public class GlobalInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object o) throws Exception {
System.out.println("--------------------Intercept攔截--------------------");
return true;
}
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("--------------------Intercept攔截返回--------------------");
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object o, Exception e) throws Exception {
System.out.println("--------------------Intercept檢視渲染回撥--------------------");
}
}
第三步:新增 AOP 切面
同樣採用配置檔案的方法
1、配置檔案中配置切面、切入點、通知,裝配 bean
<bean id="globalAspect" class="com.test.globalAspect"/>
<!--配置切面攔截方法 -->
<aop:config>
<aop:aspect ref="globalAspect">
<aop:pointcut id="globalPointcut" expression="within(com.test.controller.TestController)"/>
<aop:before pointcut-ref="globalPointcut" method="before"/>
<aop:after pointcut-ref="globalPointcut" method="after"/>
</aop:aspect>
</aop:config>
2、新建切面類
public class globalAspect {
public void before() {
System.out.println("------------------------AOP攔截----------------------");
}
public void after() {
System.out.println("------------------------AOP攔截返回------------------");
}
}
最後寫一個 Controller 方法來測試一下:
public class TestController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public void test(){
System.out.println("-----------------測試方法執行--------------------");
}
}
測試結果: