SpringMVC拦截器与Filter过滤器
????????在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如:检测用户的权限、或者将请求的信息记录到日志中,即:平常所说的“权限检测”及“日志记录”。 ???????? 当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求之后添加处理逻辑。 ???????? SpringMVC提供了Interceptor拦截器机制,用于请求的预处理和后处理。 ???????? 相比过滤器,拦截器作用的范围比较小,而拦截器几乎可以过滤所有请求。 ???????? 拦截器的作用: ???????????? [1]用户请求拦截处理; ???????????? [2]针对一个或者多个或者全部的Controller返回结果进行拦截处理; ???????????? [3]页面渲染之后,响应给浏览器之间进行拦截处理。 ???????? 过滤器和拦截器的区别? ???????????? [1]过滤器在请求到达项目组间之前工作;拦截器在前端控制器之后工作; ???????????? [2]过滤器依赖Servlet容器;拦截器是SpringMVC的,它不依赖于servlet容器,而是由Spring容器进行初始化; ???????????? Note that a filter gets configured in web.xml, a HandlerInterceptor in the application context. ???????????? [3]拦截器只能对action动态请求起作用(静态请求,例如:不会对js、css、img等静态资源的请求起到拦截作用);而过滤器可以对所有的请求起作用,无法实现细粒度的请求拦截; ???????????? [4]在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。 ???????????? [5]拦截器可以获取IOC容器中的各个bean,而过滤器就不太方便,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
Spring MVC拦截器的定义
????需要实现HandlerInterceptor接口。
package com.xwd.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AppInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("AppInterceptor preHandle");
System.out.println(handler);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("AppInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("AppInterceptor afterCompletion");
}
}
SpringMVC拦截器的配置
????需要在SpringMVC配置文件中配置HandlerInterceptor接口。 (有别于Filter过滤器,需要在web.xml中使用filter标签配置)
<!--注册拦截器-->
<mvc:interceptors>
<!--[1]拦截所有的URL请求,那么直接指定bean即可-->
<!-- <bean class="com.xwd.interceptor.AppInterceptor"></bean>-->
<!--[2]拦截特定的请求,需要使用mvc:interceptor标签来限定被拦截的访问路径-->
<mvc:interceptor>
<mvc:mapping path="/login.do"/>
<bean class="com.xwd.interceptor.AppInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
SpringMVC拦截器HandlerInterceptor接口
???? HandlerInterceptor接口中定义了3个方法,分别用于对某一个/某一些特定的请求进行预处理或者后处理。 ????【1】HandlerInterceptor拦截器 ???????? HandlerInterceptor是一个工作流程(workflow)接口,允许自定义request请求的处理执行链(handler execution chains)。对于某一组特定的handler(controller控制器),应用程序可以注册任意数量的自定义拦截器(Interceptor),在不改变原有接口实现类的前提下,实现一组通用处理行为。 ???? 【2】HandlerInterceptor拦截器工作流程 ???????? 一个HandlerInterceptor(拦截器)在HandlerAdapter(处理器适配器)触发handler(控制器之前)被调用(具体是:default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)方法被调用——请求预处理)。 ???????? 拦截器机制可以实现一组切面(Aspects)的预处理操作,例如:权限检测(Authorization Checks)、或者一组通用的处理行为(例如:区域设置-locale或者主题修改theme changes),拦截器可以分解出重复性的代码,形成一组通用的操作。 ???????????? [0]在HandlerAdapter处理器适配器调用handler(Controller控制器)之前,preHandle()方法被调用; ???????????? [1]在异步处理场景下,在没有调用postHandle()方法或者faterCompletion()方法之前(此时Handler/Controller控制器尚未执行完毕),处理器可能在一个独立线程中执行。 ???????????? [2]当并发处理器Handler(即:控制器)(concurrent handler)执行完毕,携带处理结果的Model、ModeAndView等对象被返回给HandlerAdapter处理器适配器时, postHandle()方法就会被调用,可以用于实现数据、视图的进一步处理或者数据过滤操作; ???????????? [3]当HandlerAdapter处理器适配器将封装ModeAndView对象返回给DispatcherServlet前端处理器之后,前端处理器就开始调用ViewResolver视图解析器,处理得到View视图对象,在将View视图对象响应给前端浏览器之前,faterCompletion()方法就会被调用。通常用于实现资源清理工作。 ??????? 【3】SpringMVC拦截器适用场景:与细粒度预处理任务相关的功能实现,优先考虑通过实现HandlerInterceptor接口,定义拦截器的方式。尤其是:分解出通用处理代码、权限检查等。 ????????????????? Filter过滤器适用场景:Filter过滤器更适合用来处理request请求内容、view视图内容处理,例如:multipart表单和GZip压缩处理。
附:HandlerInterceptor处理器拦截器接口源码
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 {
}
}
|