开发者社区> 朝雾轻寒> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

简介: 拦截器 1.简介 Spring MVC 中的拦截器(Interceptor)类似与 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现,底层通过动态代理模式完成。
+关注继续查看

拦截器

1.简介

Spring MVC 中的拦截器(Interceptor)类似与 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现,底层通过动态代理模式完成。

2.定义实现类

拦截器有两种实现方式:
1.实现 HandlerInterceptor 接口
2.继承 HandlerInterceptorAdapter 抽象类(看源码最底层也是通过 HandlerInterceptor 接口 实现)

3.HandlerInterceptor方法介绍

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        
        //进行逻辑判断,如果ok就返回true,不行就返回false,返回false就不会处理请求
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。
afterCompletion:在 DispatcherServlet 完全处理完请求后被调用,可用于清理资源等。

4.应用场景

1.日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等;
2.登录鉴权:如登录检测,进入处理器检测检测是否登录;

3.性能监控:检测方法的执行时间;
4.其他通用行为。

5.与 Filter 过滤器的区别

1.拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2.拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
3.拦截器只能对Controller请求起作用,而过滤器则可以对几乎所有的请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5.在Controller的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6.拦截器可以获取IOC容器中的各个bean,而过滤器不行。这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

具体实现

单个拦截器

1.新建拦截器

    public class Test1Interceptor implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("执行preHandle方法-->01");
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("执行postHandle方法-->02");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("执行afterCompletion方法-->03");
    }
}

2.配置拦截器

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /*
     * 拦截器配置
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器,添加拦截路径和排除拦截路径
        registry.addInterceptor(new Test1Interceptor()) // 添加拦截器
                .addPathPatterns("/**") // 添加拦截路径
                .excludePathPatterns(// 添加排除拦截路径
                        "/hello").order(0);//执行顺序
        super.addInterceptors(registry);
    }

}

3.测试拦截器

@RestController
public class TestController {

    @RequestMapping("/hello")
    public String getHello() {
        System.out.println("这里是Hello");
        return "hello world";
    }
    
    
    @RequestMapping("/test1")
    public String getTest1() {
        System.out.println("这里是Test1");
        return "test1 content";
    }
    
    @RequestMapping("/test2")
    public String getTest2() {
        System.out.println("这里是Test2");
        return "test2 content";
    }
}

4.单个拦截器的执行流程

通过浏览器测试:
http://127.0.0.1:8080/hello
结果:

这里是Hello

http://127.0.0.1:8080/test1http://127.0.0.1:8080/test2
结果:

执行preHandle方法-->01
这里是Test1
执行postHandle方法-->02
执行afterCompletion方法-->03

多个拦截器

1.新建两个拦截器

Test1Interceptor

public class Test1Interceptor implements HandlerInterceptor{
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("执行Test1Interceptor preHandle方法-->01");
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("执行Test1Interceptor postHandle方法-->02");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("执行Test1Interceptor afterCompletion方法-->03");
    }
}

Test2Interceptor

public class Test2Interceptor extends HandlerInterceptorAdapter{


    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("执行Test2Interceptor preHandle方法-->01");
        return true;
    }
    
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("执行Test2Interceptor postHandle方法-->02");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("执行Test2Interceptor afterCompletion方法-->03");
    }
}

2.配置拦截器

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /*
     * 拦截器配置
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器,添加拦截路径和排除拦截路径
        registry.addInterceptor(new Test1Interceptor()) // 添加拦截器1
                .addPathPatterns("/**") // 添加拦截路径
                .excludePathPatterns(// 添加排除拦截路径
                        "/hello")
                .order(0);
        registry.addInterceptor(new Test2Interceptor()) // 添加拦截器2
                .addPathPatterns("/**") // 添加拦截路径
                .excludePathPatterns(// 添加排除拦截路径
                        "/test1")
                .order(1);
        super.addInterceptors(registry);
    }

}

3.测试拦截器

@RestController
public class TestController {

    @RequestMapping("/hello")
    public String getHello() {
        System.out.println("这里是Hello");
        return "hello world";
    }
    
    
    @RequestMapping("/test1")
    public String getTest1() {
        System.out.println("这里是Test1");
        return "test1 content";
    }
    
    @RequestMapping("/test2")
    public String getTest2() {
        System.out.println("这里是Test2");
        return "test2 content";
    }
}

4.多个拦截器的执行流程

通过浏览器测试:
http://127.0.0.1:8080/test2
结果:

执行Test1Interceptor preHandle方法-->01
执行Test2Interceptor preHandle方法-->01
这里是Test2
执行Test2Interceptor postHandle方法-->02
执行Test1Interceptor postHandle方法-->02
执行Test2Interceptor afterCompletion方法-->03
执行Test1Interceptor afterCompletion方法-->03

通过示例,简单的说多个拦截器执行流程就是先进后出

简单的 token 判断示例

1.拦截器

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("执行Test1Interceptor preHandle方法-->01");
        
        String token = request.getParameter("token");
        if (StringUtils.isEmpty(token)) {            
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("token不存在");
            return false;
        }
        return true;
    }

2.测试及结果

未传token:

执行Test1Interceptor preHandle方法-->01

传token:

执行Test1Interceptor preHandle方法-->01
页码:1
页码大小:10
执行Test1Interceptor postHandle方法-->02
执行Test1Interceptor afterCompletion方法-->03

示例代码

github

码云

非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

原文标题:Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

原文地址: https://www.zwqh.top/article/info/18

如果文章对您有帮助,请扫码关注下我的公众号,文章持续更新中...

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Spring Boot中使用JUnit5进行单元测试
Spring Boot中使用JUnit5进行单元测试
7 0
SpringBoot——SpringBoot集成MyBatis
SpringBoot——SpringBoot集成MyBatis
166 0
redis在springboot中的使用
redis在springboot中的使用
55 0
Spring Boot 应用可视化监控,一目了然!
Spring Boot 应用可视化监控,一目了然!
419 0
Spring Boot 实现定时任务的 4 种方式
定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
207 0
SpringBoot【整合JSP】
SpringBoot中默认是不支持jsp的,但是我们某些情况下可以又需要用到,所以本文记录下SpringBoot整合jsp的过程
39 0
SpringBoot使用RabbitMQ(二)
springboot使用rabbitmq发送回调队列
4919 0
SpringBoot整合elasticsearch
在这一篇文章开始之前,你需要先安装一个ElasticSearch,如果你是mac或者linux可以参考https://www.jianshu.com/p/e47b451375ea,如果是windows可以自定百度一下。
2452 0
springboot(四):thymeleaf使用详解
在上篇文章springboot(二):web综合开发中简单介绍了一下thymeleaf,这篇文章将更加全面详细的介绍thymeleaf的使用。thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎。 thymeleaf介绍 简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可
1395 0
+关注
朝雾轻寒
持之以恒
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Spring Boot 2.5开发实战
立即下载
Java Spring Boot开发实战系列课程【第15讲】:Spring Boot 2.0 API与Spring REST Docs实战
立即下载
Java Spring Boot开发实战系列课程【第7讲】:Spring Boot 2.0安全机制与MVC身份验证实战(Java面试题)
立即下载