过滤器:基于 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("-----------------测试方法执行--------------------");
}
}
测试结果: