赞
踩
目录
SpringMVC的拦截器(Interceptor)也是AOP思想的一种实现方式。它与Servlet的过滤器(Filter)功能类似,主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。
拦截器和过滤器的区别:
1.拦截器是SpringMVC组件,而过滤器是Servlet组件。
2.拦截器不依赖Web容器,过滤器依赖Web容器。
3.拦截器只能对控制器请求起作用,而过滤器可以对所有的请求起作用。
4.拦截器可以直接获取IOC容器中的对象,而过滤器不太方便获取。
1.使用Maven创建SpringMVC的Web项目
2.创建控制器方法MyController1
- @Controller
- public class MyController1 {
-
- @RequestMapping("/m1")
- public String m1(){
- System.out.println("控制器方法m1");
- return "result";
- }
- }
3.创建拦截器类MyInterceptor,该类实现HandlerInterceptor接口,需要重写三个方法:
(1)preHandle:请求到达Controller前执行的方法,返回值为true时,请求可以通过拦截器,返回值为false时,请求不能通过拦截器,即被拦截器拦截
(2)postHandle:跳转到JSP前执行的方法
(3)afterCompletion:跳转到JSP执行后的方法
- public class MyInterceptor implements HandlerInterceptor {
- //请求到达Controller前执行
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("拦截器1:请求到达Controller前");
- return false;
- }
-
- //跳转到JSP页面前执行,此时可以向request域添加数据,也就是这里的name可以传到request域中
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面前");
- request.setAttribute("name","坏蛋");
- }
-
- //跳转到JSP页面后执行,此时不能向request域添加数据,也就是这里的age传不到request域中
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面后");
- request.setAttribute("age",10);
- }
- }
4.编写JSP页面 result.jsp
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>结果</title>
- </head>
- <body>
- <h3>name:${requestScope.name}</h3>
- <h3>age:${requestScope.age}</h3>
- </body>
- </html>
5.在SpringMVC核心配置文件springmvc.xml中配置拦截器
- <!-- 配置拦截器 -->
- <mvc:interceptors>
- <mvc:interceptor>
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/**"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
- </mvc:interceptor>
- </mvc:interceptors>
1.当 preHandle方法返回值为false时 :
当preHandle方法返回值为false时,请求会被拦截器拦截,不会到达Controller控制器。
2.当 preHandle方法返回值为true时 :
由结果可以看出,当preHandle方法返回值为true时,请求可以通过拦截器,不会被拦截器拦截,所以先执行preHandle方法,然后到达Controller层执行方法,再跳转到JSP页面,在跳转到JSP页面前先执行postHandle,等到JSP页面执行完毕再执行afterCompletion方法。同时,PostHandle方法在JSP页面前执行,所以可以向request域中添加数据,而afterCompletion方法在JSP页面执行后执行,所以不能向request域中添加数据。
- <!-- 配置拦截器 -->
- <mvc:interceptors>
- <!-- 全局拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
- </mvc:interceptors>
==
- <!-- 配置拦截器 -->
- <mvc:interceptors>
- <mvc:interceptor>
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/**"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
- </mvc:interceptor>
- </mvc:interceptors>
如下代码中,在<mvc:mapping path="">标签中配置指定的区域
- <!-- 配置拦截器 -->
- <mvc:interceptors>
- <mvc:interceptor>
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/Student/MyController"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
- </mvc:interceptor>
- </mvc:interceptors>
如果一个URL能够被多个拦截器所拦截,全局拦截器最先执行,其他拦截器根据配置文件中配置的从上到下执行,如上图,先执行拦截器1,再执行拦截器2,再执行Handler控制器,然后返回去先执行postHandle2-->postHandle1-->afterCompletion2-->afterCompletion1
1.编写拦截器类MyInterceptor2
- public class MyInterceptor implements HandlerInterceptor {
- //请求到达Controller前执行
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("拦截器1:请求到达Controller前");
- return true;
- }
-
- //跳转到JSP页面前执行,此时可以向request域添加数据,也就是这里的name可以传到request域中
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面前");
- // request.setAttribute("name","坏蛋");
- }
-
- //跳转到JSP页面后执行,此时不能向request域添加数据,也就是这里的age传不到request域中
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面后");
- // request.setAttribute("age",10);
- }
- }
- public class MyInterceptor implements HandlerInterceptor {
- //请求到达Controller前执行
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("拦截器1:请求到达Controller前");
- return true;
- }
-
- //跳转到JSP页面前执行,此时可以向request域添加数据,也就是这里的name可以传到request域中
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面前");
- // request.setAttribute("name","坏蛋");
- }
-
- //跳转到JSP页面后执行,此时不能向request域添加数据,也就是这里的age传不到request域中
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("拦截器1:跳转到JSP页面后");
- // request.setAttribute("age",10);
- }
- }
2.在springmvc核心配置文件springmvc.xml中配置拦截器链
- <!-- 配置拦截器 -->
- <mvc:interceptors>
- <!-- 拦截器1 -->
- <mvc:interceptor>
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/**"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
- </mvc:interceptor>
-
- <!-- 拦截器2 -->
- <mvc:interceptor>
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/**"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.MyInterceptor2"></bean>
- </mvc:interceptor>
- </mvc:interceptors>
3.请求结果:
1.当MyInterceptor、MyInterceptor2中的preHandle方法返回值同时为true时,preHandle()方法顺序执行,postHandle()、afterCompletion()方法逆序执行。
拦截器执行顺序:
preHandle1()-->preHandle2()-->Handler-->postHandle1()-->postHandle2()-->afterCompletion1()-->afterCompletion2()
2. 当MyInterceptor中的preHandle方法返回值为false,MyInterceptor2中的preHandle方法返回值为true时, 在preHandle1()后面的preHandle()、postHandle()都不会执行。
拦截器执行顺序:
preHandle1()拦截,无后续;
3.当MyInterceptor中的preHandle方法返回值为true,MyInterceptor2中的preHandle方法返回值为false时,拦截器1、拦截器2的preHandle()都会执行,但Handler和postHandle()不会执行,同时afterCompletion()只执行对应preHandle()方法返回值为true拦截器。
拦截器执行顺序:
preHandle1()-->preHandle2()-->afterCompletion1()
结论:
当有多个拦截器对同一个作用域进行拦截时:
1.preHandle()方法顺序执行,postHandle()、afterCompletion()方法逆序执行。
2.只要有一个preHandle()拦截,在它之后的preHandle()、postHandle()都不会执行。
3.只要相应的preHandle()放行,对应的afterCompletion()就会执行。
在系统中,我们需要将所有响应中的一些敏感词替换为 *** ,此时可以使用拦截器达到要求:
1.编写控制器方法MyController2
- @Controller
- public class MyController2 {
-
- @RequestMapping("/m2")
- public String m2(Model model){
- model.addAttribute("name","大笨蛋");
- return "result";
- }
- }
2.编写敏感词拦截器SensitiveWordInterceptor
- //敏感词拦截器
- public class SensitiveWordInterceptor implements HandlerInterceptor {
- @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 {
- //定义敏感词列表
- String[] sensitiveWords = {"坏人","笨蛋","暴力"};
- //获取Model中的所有数据
- Map<String, Object> model = modelAndView.getModel();
- Set<Map.Entry<String, Object>> entries = model.entrySet();
- //遍历model,替换敏感词
- for (Map.Entry<String, Object> entry : entries) {
- String key = entry.getKey();
- String value = entry.getValue().toString();
- //将model值和敏感词列表遍历比对
- for (String sensitiveWord:sensitiveWords){
- //只要数据模型的值包含敏感词,替换
- if (value.contains(sensitiveWord)){
- String newStr = value.replaceAll(sensitiveWord,"***");
- model.put(key,newStr);
- }
- }
- }
- }
- }
3.在springmvc核心配置文件springmvc.xml中配置拦截器链
- <!-- 配置拦截器 -->
- <mvc:interceptors>
-
- <mvc:interceptor>
- <!-- 敏感词拦截器-->
- <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
- <mvc:mapping path="/**"/>
- <!-- 配置拦截器对象,指定用哪个拦截器-->
- <bean class="com.itbaizhan.interceptor.SensitiveWordInterceptor"></bean>
- </mvc:interceptor>
- </mvc:interceptors>
拦截之前:
拦截之后:
1.在SpringMVC中,定义拦截器需要实现“HandlerInterceptor ”接口
2.在SpringMVC配置文件中,配置拦截器的标签为“<mvc:interceptor>”
3.在SpringMVC中,全局拦截器会拦截“所有控制器处理的URL”
4.在SpringMVC中,拦截器链的执行顺序为“preHandle() 顺序执行, postHandle() 、afterCompletion()逆序执行。”
5.在SpringMVC中,只要相应的 preHandle() 放行,“afterComletion() 就会执行。”
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。