目录

一、SpringMVC 拦截器_拦截器简介

二、SpringMVC 拦截器_拦截器使用

三、SpringMVC 拦截器_拦截器作用域

四、SpringMVC 拦截器_拦截器链与执行顺序

五、SpringMVC 拦截器_拦截器过滤敏感词案例

六、知识点整理:


一、SpringMVC 拦截器_拦截器简介

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效

SpringMVC的拦截器(Interceptor)也是AOP思想的一种实现方式。它与Servlet的过滤器(Filter)功能类似,主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

拦截器和过滤器的区别:

1.拦截器是SpringMVC组件,而过滤器是Servlet组件。

2.拦截器不依赖Web容器,过滤器依赖Web容器。

3.拦截器只能对控制器请求起作用,而过滤器可以对所有的请求起作用。

4.拦截器可以直接获取IOC容器中的对象,而过滤器不太方便获取。

二、SpringMVC 拦截器_拦截器使用

项目结构:

springmvc 过滤器编码不生效 springmvc的过滤器_前端_02

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>

6.请求结果:

1.当 preHandle方法返回值为false时 :

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_03

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_04

当preHandle方法返回值为false时,请求会被拦截器拦截,不会到达Controller控制器。

2.当 preHandle方法返回值为true时 :

springmvc 过滤器编码不生效 springmvc的过滤器_spring_05

 

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_06

 由结果可以看出,当preHandle方法返回值为true时,请求可以通过拦截器,不会被拦截器拦截,所以先执行preHandle方法,然后到达Controller层执行方法,再跳转到JSP页面,在跳转到JSP页面前先执行postHandle,等到JSP页面执行完毕再执行afterCompletion方法。同时,PostHandle方法在JSP页面前执行,所以可以向request域中添加数据,而afterCompletion方法在JSP页面执行后执行,所以不能向request域中添加数据。

三、SpringMVC 拦截器_拦截器作用域

1.全局拦截器


全局拦截器可以拦截所有控制器处理的URL,作用等于/**, 配置方式如下:


<!-- 配置拦截器 -->
    <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>

2.局部拦截器

如下代码中,在<mvc:mapping path="">标签中配置指定的区域

<!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截器的作用路径,/**表示作用于所有控制器-->
            <mvc:mapping path="/Student/MyController"/>
            <!-- 配置拦截器对象,指定用哪个拦截器-->
            <bean class="com.itbaizhan.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

四、SpringMVC 拦截器_拦截器链与执行顺序

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_07

如果一个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.请求结果:

springmvc 过滤器编码不生效 springmvc的过滤器_前端_08

 1.当MyInterceptor、MyInterceptor2中的preHandle方法返回值同时为true时,preHandle()方法顺序执行,postHandle()、afterCompletion()方法逆序执行。

拦截器执行顺序:

preHandle1()-->preHandle2()-->Handler-->postHandle1()-->postHandle2()-->afterCompletion1()-->afterCompletion2()

springmvc 过滤器编码不生效 springmvc的过滤器_拦截器_09

 2. 当MyInterceptor中的preHandle方法返回值为false,MyInterceptor2中的preHandle方法返回值为true时, 在preHandle1()后面的preHandle()、postHandle()都不会执行。

拦截器执行顺序:

preHandle1()拦截,无后续;

springmvc 过滤器编码不生效 springmvc的过滤器_java_10

3.当MyInterceptor中的preHandle方法返回值为true,MyInterceptor2中的preHandle方法返回值为false时,拦截器1、拦截器2的preHandle()都会执行,但Handler和postHandle()不会执行,同时afterCompletion()只执行对应preHandle()方法返回值为true拦截器。

拦截器执行顺序:

preHandle1()-->preHandle2()-->afterCompletion1()

springmvc 过滤器编码不生效 springmvc的过滤器_java_11

结论:

当有多个拦截器对同一个作用域进行拦截时:

1.preHandle()方法顺序执行,postHandle()、afterCompletion()方法逆序执行。

2.只要有一个preHandle()拦截,在它之后的preHandle()、postHandle()都不会执行。

3.只要相应的preHandle()放行,对应的afterCompletion()就会执行。

五、SpringMVC 拦截器_拦截器过滤敏感词案例

springmvc 过滤器编码不生效 springmvc的过滤器_spring_12

 在系统中,我们需要将所有响应中的一些敏感词替换为 *** ,此时可以使用拦截器达到要求:

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>

4.请求结果:

拦截之前:

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_13

拦截之后: 

springmvc 过滤器编码不生效 springmvc的过滤器_springmvc 过滤器编码不生效_14

 

六、知识点整理:

1.在SpringMVC中,定义拦截器需要实现HandlerInterceptor 接口

2.在SpringMVC配置文件中,配置拦截器的标签为<mvc:interceptor>”

3.在SpringMVC中,全局拦截器会拦截“所有控制器处理的URL”

4.在SpringMVC中,拦截器链的执行顺序为preHandle() 顺序执行, postHandle() 、afterCompletion()逆序执行。”

5.在SpringMVC中,只要相应的 preHandle() 放行,afterComletion() 就会执行。”