SpringMVC(6)------ 拦截器

拦截器概念(重点)

image-20211004212653038

拦截器(Interceptor) 是一种动态拦截方法调用的机制

简单来说就是在控制方法调用前后的干事情的

  • 作用

    1.在指定的方法调用前后执行预先设定后的的代码

    2.阻止原始方法的执行

  • 核心原理:AOP思想

  • 拦截器链:多个拦截器按照一定的顺序,对原始被调用功能进行增强

    比如:去银行对服务器进行维护,进去时是重重防护,并获取权限进去,干完活处理,又要按之前的顺序倒序返回在之前关卡所得到的内容

image-20211004213329226

过滤器( Filter)与拦截器(Interceptor)的区别

1.拦截内容不同: Filter(过滤器)对所有访问进行增强,Interceptor(拦截器)仅针对springMVC的访问进行增强

2.归属不同: Filter属于servlet技术,Interceptor 属于SpringMVC技术

拦截器作用:增强

自定义拦截器(重点)

package com.yy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Controller
public class InterceptorController {
    @RequestMapping("/handleRun")
    public String handleRun() {
        System.out.println("业务处理器运行------------main");
        return "page.jsp";
    }
}

第一步:制作拦截器功能类(通知)

image-20211004213831862

  • MyInterceptor.java拦截器功能类测试代码

    package com.yy.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    //自定义拦截器需要实现HandleInterceptor接口,实现接口默认是不会报错的,需要自己去重写下面这三个抽象方法
    public class MyInterceptor implements HandlerInterceptor {
        //处理器运行之前执行
        @Override
        public boolean preHandle(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Object handler) throws Exception {
            System.out.println("前置运行----a1");
            //返回值为false将拦截原始处理器的运行,表示不向下运行,这时后面的postHandle和afterCompletion不会继续运行了
            //返回值是true代表向下放行
            //如果配置多拦截器,返回值为false将终止当前拦截器后面配置的拦截器的运行
            return true;
        }
    
        //处理器运行之后执行
        @Override
        public void postHandle(HttpServletRequest request,
                               HttpServletResponse response,
                               Object handler,
                               ModelAndView modelAndView) throws Exception {
            System.out.println("后置运行----b1");
        }
    
        //所有拦截器的后置执行全部结束后,执行该操作
        @Override
        public void afterCompletion(HttpServletRequest request,
                                    HttpServletResponse response,
                                    Object handler,
                                    Exception ex) throws Exception {
            System.out.println("完成运行----c1");
        }
    
        //三个方法的运行顺序为    preHandle -> postHandle -> afterCompletion
        //如果preHandle返回值为false,三个方法仅运行preHandle
    }
    

    jsp代码

    <%@page pageEncoding="UTF-8" language="java" contentType="text/html;UTF-8" %>
    <html>
    <body>
    <h1>拦截器测试中...</h1>
    </body>
    </html>
    

第二步:配置拦截器的执行位置(切入点)

image-20211004213847445

  • 配置拦截器的spring-mvc.xml的代码

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.yy"/>
        <mvc:annotation-driven/>
        <!--开启拦截器使用-->
        <mvc:interceptors>
            <!--开启具体的拦截器的使用,可以配置多个-->
            <mvc:interceptor>
                <!--设置拦截器的拦截路径,支持*通配-->
                <!--/**         表示拦截所有映射-->
                <!--/*          表示拦截所有/开头的映射-->
                <!--/user/*     表示拦截所有/user/开头的映射-->
                <!--/user/add*  表示拦截所有/user/开头,且具体映射名称以add开头的映射-->
                <!--/user/*All  表示拦截所有/user/开头,且具体映射名称以All结尾的映射-->
                <mvc:mapping path="/*"/>
                <mvc:mapping path="/**"/>
                <mvc:mapping path="/handleRun*"/>
                <!--设置拦截排除的路径,配置/**或/*,达到快速配置的目的-->
                <mvc:exclude-mapping path="/b*"/>
                <!--指定具体的拦截器类-->
                <bean class="com.yy.interceptor.MyInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
    
    </beans>
    

运行结果:

前置运行----a1
业务处理器运行------------main
后置运行----b1
完成运行----c1

拦截器参数

参数分析

HttpServletRequest:请求
HttpServletResponse:响应

handler:就是封装了Method方法,简单来说就是操作与原始方法相关的东西,就是通过这个对象去操作

ModelAndView:是handle运行完,返回的东西。通过这个参数可以对执行完的结果进行修正,例如如果你出现了什么问题,会让你去B页面

Exception:如果InterceptorController抛出异常,在这个afterCompletion方法里面可以拦截过滤,然后根据异常做处理

preHandle方法handle运行之前要做的事,写在这个方法里面,例如做参数的格式处理、权限校验等等

postHandle方法运行之后对里面数据进行处理。例如它返回了一个json数据,在这里面我想再加一条JSON数据,就需要在这里面做,比如如果你之前返回的是页面A,我在这里可以换成页面B,比如你之前登录的有session状态,我在这里可以清掉

afterCompletion方法:就干一件事,如果里面有异常,在这里可以根据异常对它进行处理

image-20211005132250629

image-20211005132311821

image-20211005132323953

拦截器配置项

image-20211005132604812

拦截器工作流程分析

image-20211005130055001

拦截器链配置

当配置多个拦截器时,形成拦截器链

拦截器链的运行顺序参照配置的先后顺序

当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行

当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
image-20211005133425271

  • spring-mvc.xml,在这里面我又新建了两个拦截器,基本上与上面的拦截器配置一样,只不过是打印的数据不一样,在这里便不把另外两个拦截器的java代码给出

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.yy"/>
        <mvc:annotation-driven/>
        <!--开启拦截器使用-->
        <mvc:interceptors>
            <!--开启具体的拦截器的使用,可以配置多个-->
            <mvc:interceptor>
                <!--设置拦截器的拦截路径,支持*通配-->
                <!--/**         表示拦截所有映射-->
                <!--/*          表示拦截所有/开头的映射-->
                <!--/user/*     表示拦截所有/user/开头的映射-->
                <!--/user/add*  表示拦截所有/user/开头,且具体映射名称以add开头的映射-->
                <!--/user/*All  表示拦截所有/user/开头,且具体映射名称以All结尾的映射-->
                <mvc:mapping path="/*"/>
                <mvc:mapping path="/**"/>
                <mvc:mapping path="/handleRun*"/>
                <!--设置拦截排除的路径,配置/**或/*,达到快速配置的目的-->
                <mvc:exclude-mapping path="/b*"/>
                <!--指定具体的拦截器类-->
                <bean class="com.yy.interceptor.MyInterceptor"/>
            </mvc:interceptor>
    <!--        &lt;!&ndash;配置多个拦截器,配置顺序即为最终运行顺序&ndash;&gt;-->
            <mvc:interceptor>
                <mvc:mapping path="/*"/>
                <bean class="com.yy.interceptor.MyInterceptor2"/>
            </mvc:interceptor>
            <mvc:interceptor>
                <mvc:mapping path="/*"/>
                <bean class="com.yy.interceptor.MyInterceptor3"/>
            </mvc:interceptor>
        </mvc:interceptors>
    
    </beans>
    
  • 正常运行结果(全为true)

    前置运行----a1
    前置运行------a2
    前置运行--------a3
    业务处理器运行------------main
    后置运行--------b3
    后置运行------b2
    后置运行----b1
    完成运行--------c3
    完成运行------c2
    完成运行----c1

责任链模式

责任链模式是一种行为模式

特征:

  • 沿着一条预先设定的任务链顺序执行, 每个节点具有独立的工作任务

优势:

  • 独立性:只关注当前节点的任务,对其他任务直接放行到下一节点
  • 隔离性:具备链式传递特征,无需知晓整体链路结构,只需等待请求到达后进行处理即可
  • 灵活性:可以任意修改链路结构动态新增或删减整体链路责任
  • 解耦:将动态任务与原始任务解耦

弊端:

  • 链路过长时,处理效率低下
  • 可能存在节点上的循环引用现象,造成死循环,导致系统崩溃

拦截器链的运行顺序

  • preHandler:与配置顺序相同,必定运行
  • postHandler:与配置顺序相反,可能不运行;
  • afterCompletion:与配置顺序相反,可能不运行
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

?abc!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值