参考以下博文:
http://jinnianshilongnian.iteye.com/blog/1670856
http://www.blogjava.net/wmcoo/articles/333752.html
http://www.blogjava.net/atealxt/archive/2009/09/20/spring_mvc_annotation_interceptor_gae.html
http://my.oschina.net/boonya/blog/92077
spring mvc 可以采用实现HandlerInterceptor 接口 或 继承HandlerInterceptorAdapter类的方法实现。
app-servlet.xml的配置相同:
<!-- 拦截器 --> <mvc:interceptors> <bean class="cwz.interceptor.SysInterceptor" /> <mvc:interceptor> <mvc:mapping path="/edit.html"/> <bean class="cwz.interceptor.UserInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
其中
SysInterceptor 是系统级的拦截器 UserInterceptor 是作用于path="/edit.html"请求的拦截器
SysInterceptor实现了HandlerInterceptor 接口;UserInterceptor继承自HandlerInterceptorAdapter类,并重写了preHandle方法:
package cwz.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 SysInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception { System.out.println("test interceptor sysinterceptor_preHandle"); System.out.println(request.getRequestURL() + "-" + request.getRequestURI()); return true; //To change body of implemented methods use File | Settings | File Templates. } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception { System.out.println("test interceptor sysinterceptor_postHandle"); //To change body of implemented methods use File | Settings | File Templates. } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception { //To change body of implemented methods use File | Settings | File Templates. System.out.println("test interceptor sysinterceptor_afterCompletion"); } }
UserInterceptor.java
package cwz.interceptor; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created By cwz * Date: 14-7-28 下午3:03 * <p/> * Introduction : */ public class UserInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("---------UserInterceptor.preHandle-----------"); return false; } }
说明:
发起请求,进入拦截器链,运行所有拦截器的preHandle方法
1.当preHandle方法返回false时,从当前拦截器往回执行所有拦截器的afterCompletion方法,再退出拦截器链。
2.当preHandle方法全为true时,执行下一个拦截器,直到所有拦截器执行完。再运行被拦截的Controller。然后进入拦截器链,运行所有拦截器的postHandle方法,完后从最后一个拦截器往回执行所有拦截器的afterCompletion方法.
当有拦截器抛出异常时,会从当前拦截器往回执行所有拦截器的afterCompletion方法.
结合本例,由于UserInterceptor 的 preHandle方法返回false,故执行流程应该是
SysInterceptor.preHandle()——UserInterceptor.preHandle()——SysInterceptor.afterCompletion()
打印的结果:
test interceptor sysinterceptor_preHandle
http://localhost:8080/edit.html-/edit.html
---------UserInterceptor.preHandle-----------
test interceptor sysinterceptor_postHandle
test interceptor sysinterceptor_afterCompletion
若返回true,则执行结果:
test interceptor sysinterceptor_preHandle
http://localhost:8080/edit.html-/edit.html
---------UserInterceptor.preHandle-----------
test interceptor sysinterceptor_postHandle
test interceptor sysinterceptor_afterCompletion
-------------------------------------------------------------------------------------------------------------
引用http://jinnianshilongnian.iteye.com/blog/1670856 中的说明及流程图:
我们可能注意到拦截器一个有3个回调方法,而一般的过滤器Filter才两个,这是怎么回事呢?马上分析。
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
正常流程:
中断流程: