07 SpringMVC 拦截器

目录

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

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

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

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

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

六、知识点整理:


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

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

拦截器和过滤器的区别:

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

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

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

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

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

项目结构:

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时 :

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

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

 

 由结果可以看出,当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 拦截器_拦截器链与执行顺序

 如果一个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()就会执行。

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

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

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

拦截之前:

拦截之后: 

 

六、知识点整理:

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

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

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

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值