===============================拦截器详解===================================
类似于servlet中的过滤器filter
拦截器常见的应用场景
日志记录
权限检查
性能监控
通用行为
openSessionInView
拦截器接口
public interface HandlerInterceptor {
//实现拦截器的预处理
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
//实现处理器的后处理
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
//请求完毕后的回调方法
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
拦载器适配器
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}
运行流程
HandlerInterceptor1.preHandle
HandlerInterceptor2.preHandle
handlerAdapter
HandlerInterceptor2.postHandle
HandlerInterceptor1.postHandle
view渲染
HandlerInterceptor2.afterCompletion
HandlerInterceptor1.afterCompletion
如果是 HandlerInterceptor2 中断的流程(preHandle 返回 false),此处仅调用它之前拦截器(HandlerInterceptor1HandlerInterceptor1)的 preHandle 返回 true 的 afterCompletion 方法。
每个handlerMapping可以有自已的拦截器
按order值的大小,顺序执行handlerMapping
执行完拦截后,交给目标处理器
springMVC配置文件的三种配置方法:
方法一:
<!-- 拦截器 -->
<mvc:interceptors>
<bean class="cn.yue.mvc.MyInteceptor" />
</mvc:interceptors>
方法二:
<!-- 拦截匹配的url -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/*" />
<bean class="cn.yue.mvc.MyInteceptor" />
</mvc:interceptor>
</mvc:interceptors>
方法三:
<!-- handlerMapping上的拦截器 -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.mvc.MyInteceptor"></bean>
</list>
</property>
</bean>
注:此时不能使用<mvc:annotation-driven />
--------------------------正常流程
自定义拦截器
public class NormalHandlerInterceptor1 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("=====NormalHandlerInterceptor1 preHandle=====");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=====NormalHandlerInterceptor1 postHandle=====");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=====NormalHandlerInterceptor1 afterCompletion=====");
super.afterCompletion(request, response, handler, ex);
}
}
NormalHandlerInterceptor2同1一样只是打印信息不同
自定义控制器
public class TestHandlerIngerceptorController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("=TestHandlerInterceptor=");
return new ModelAndView("test");
}
}
spring配置文件中添加如下内容
<!-- 测试自定义拦截器中方法的执行顺序 -->
<bean name="/test"
class="cn.yue.mvc.controller.TestHandlerIngerceptorController" />
<bean id="handlerInterceptor1" class="cn.yue.mvc.interceptor.NormalHandlerInterceptor1" />
<bean id="handlerInterceptor2" class="cn.yue.mvc.interceptor.NormalHandlerInterceptor2" />
<!-- 指定拦截器链,拦截器的执行顺序就在此指定 -->
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1" />
<ref bean="handlerInterceptor2" />
</list>
</property>
</bean>
测试:http://localhost:8089/test
=====NormalHandlerInterceptor1 preHandle=====
=====NormalHandlerInterceptor2 preHandle=====
=TestHandlerIngerceptorController=
=====NormalHandlerInterceptor2 postHandle=====
=====NormalHandlerInterceptor1 postHandle=====
===============test.jsp
=====NormalHandlerInterceptor2 afterCompletion=====
=====NormalHandlerInterceptor1 afterCompletion=====
------------------------------中断流程
修改NormalHandlerInterceptor2如下内容
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 正常流程
// System.out.println("=====NormalHandlerInterceptor2 preHandle=====");
// return super.preHandle(request, response, handler);
// 中断流程
System.out.println("=====HandlerInterceptor2 preHandle=====");
response.getWriter().print("break");// 流程中断的话需要我们进行响应的处理
return false;// 返回 false 表示流程中断
}
测试控制台输出结果如下:
=====NormalHandlerInterceptor1 preHandle=====
=====HandlerInterceptor2 preHandle=====
=====NormalHandlerInterceptor1 afterCompletion=====
拦截器的应用
性能监控(记录请求的处理时间)
登录检测
为了加强通用性,最好使用servlet规范中的过滤器filter实现
参考:http://jinnianshilongnian.iteye.com/blog/1752171