拦截器的作用
对访问目标程序前,后进行功能的扩展,类似于Filter作用
拦截器的开发过程
自定义拦截器,需要实现org.springframework.web.servlet.HandlerInterceptor接口
//自定义拦截器
public class LogInterceptor implements HandlerInterceptor {
//在执行jsp之后执行
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("LogInterceptor - afterCompletion...");
}
//在执行目标方法后,jsp执行前执行
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
System.out.println("LogInterceptor - postHandle...");
}
//在执行目标方法前执行
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println("LogInterceptor - preHandle...");
//返回true 相当于放行请求,执行后面的拦截器或目标方法。
//返回false 后面的目标方法,拦截器,jsp等都不执行了,主要用于权限控制
return true;
}
}
声明拦截器配置
<!-- 声明拦截器 -->
<mvc:interceptors>
<bean id="logInterceptor" class="com.xiao.zhen.springmvc.interceptor.LogInterceptor"></bean>
</mvc:interceptors>
多个拦截器执行过程
1、当俩个拦截器都实现放行操作时,顺序为preHandle 1,preHandle 2,postHandle 2,postHandle 1,afterCompletion 2,afterCompletion 1
2、当第一个拦截器preHandle返回false,也就是对其进行拦截时,第二个拦截器是完全不执行的,第一个拦截器只执行preHandle部分。
3、当第一个拦截器preHandle返回true,第二个拦截器preHandle返回false,顺序为preHandle 1,preHandle 2 ,afterCompletion 1
拦截器对象是在服务器启动时创建的,单例的
拦截器声明路径的拦截配置
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑
三个方法的作用
<!-- 声明拦截器 -->
<mvc:interceptors>
//对所有都拦截
<bean id="logInterceptor" class="com.xiao.zhen.springmvc.interceptor.LogInterceptor"></bean>
<mvc:interceptor> //进一步细化
<mvc:mapping path="/springmvc/*"/> //对谁进行拦截
<mvc:exclude-mapping path="/springmvc/abc"/> //不对谁进行拦截
<bean id="log2Interceptor" class="com.xiao.zhen.springmvc.interceptor.Log2Interceptor"> </bean>
</mvc:interceptor>
</mvc:interceptors>
开发拦截器除了可以实现HandlerIntercptor接口,还可以继承HandlerInterceptorAdapter适配器类.
多个拦截器执行,体现了责任链设计模式.
-
责任链设计模式:
将复杂的业务逻辑拆分成若干个元素,将这些元素纳入到一个链式的结构中,每一个元素的执行有必要调用下一个元素的执行,好处是局部高度的扩展性.可以任意增加,减少元素个数,也可以调整元素的执行顺序. - preHandle
- postHandle
后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null
- afterCompletion
整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion
过滤器和拦截器的区别
1.过滤器是servlet中的对象,拦截器是框架中的对象
2.过滤器实现Filter接口对象,拦截器是实现HandleInterceptor
3.过滤器是用来设置request,response参数、属性,侧重对数据的过滤;拦截器是用来验证请求的,能截断请求。
4.过滤器是在拦截器之前执行的
5.过滤器是tomcat服务器创建的对象,拦截器是springmvc容器创建的对象
6.过滤器是一个执行时间点;拦截器是三个执行时间点
7.过滤器可以处理jsp、js、html等;拦截器是侧重拦截Controller的对象,如果你的请求不能被DispatcherServlet接收,这个请求不会执行拦截器的内容
8.拦截器拦截普通类方法执行,过滤器过滤servlet请求响应
过滤器:
public class AuthFilter implements Filter {
private final static Logger LOGGER = LoggerFactory.getLogger(AuthFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
try {
if (req.getMethod().equalsIgnoreCase("OPTIONS")) {
chain.doFilter(request, response);
} else {
String accessToken = req.getHeader(HeaderEnum.ACCESS_TOKEN.getKey());
String uidStr = req.getHeader(HeaderEnum.UID.getKey());
String url = req.getRequestURI();
// 业务处理,例如业务校验
chain.doFilter(request, response);
}
} catch (Exception e) {
LOGGER.error("user verify api/token/locked error:{}", e);
}
}
@Override
public void destroy() {
}
private Boolean isExclude(String url) {
List<String> excludeList = new ArrayList<>();
excludeList.add("api/url1");
excludeList.add("/api/url2");
return excludeList.contains(url);
}