SpringBoot(八)拦截器Interceptor

上篇介绍了Filter过滤器的使用,提起过滤器,就不得不再提起另外一个叫做拦截器的东西。两者的作用类似,都可以实现拦截请求的作用,但其实两者有着非常大的区别。本篇,我们就来学习下拦截器的使用。

如果你是新手,且没看过我之前的一系列SpringBoot文章,建议至少看一下这一篇:

SpringBoot(四)SpringBoot搭建简单服务端_springboot做成服务_heart荼毒的博客-CSDN博客​​​​​​​

如果你想从头到尾系统地学习,欢迎关注我的SpringBoot专栏,持续更新:

https://blog.csdn.net/qq_21154101/category_12359403.html

一、拦截器Interceptor​​​​​​​

拦截器跟过滤器有着非常相似的作用,过滤器可以做到的事情,拦截器也可以做到,甚至可以做到更好。

Filter是Servlet的一个概念或者组件,而Interceptor是Spring的一个概念或组件。大家都知道,做web开发,最原始的时候不是用Spring或者SpringBoot,而是Jsp + servlet(我至今还记得大三的时候在机房上机,在那配置tomcat,配置Servlet....)。Spring以及后续的SpringBoot都是为了简化开发,在这里我们暂且不去详细的比较二者。

同样的,拦截器是位于客户端可服务端中间的组件,可以有0-多个,跟过滤器类似:

二、自定义拦截器

SpringBoot提供了对拦截器的支持,使用也非常方便。首先,实现HandlerInterceptor接口,创建一个拦截器。在这里,仅模拟拦截器的实现,写了个非常简单的逻辑,如果请求串包含"sb"就拦截,否则放行:

java 复制代码
package com.zhaojun.server.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器处理中...");
        String queryString = request.getQueryString();
        if (queryString.contains("sb")) {
            System.out.println("拦截");
            return false;
        }
        System.out.println("放行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器处理结束...");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("请求结束...");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

接下来,需要去配置一下拦截器,创建一个Config类,实现WebMvcConfigurer接口,并且添加@Configuration注解:

java 复制代码
package com.zhaojun.server.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/login");
    }
}

三、验证拦截器是否生效

接下来,测试下拦截器是否生效。首先,使用不包含sb的url进行请求http://localhost:8080/login?name=zj&phone=156532890870&password=123456

看代码执行的流程:

可以看到,首先走到了preHandle,因为不包含特定字符sb,放行。然后依次走到了postHandle和afterCompletion。并且,因为我是接着上一篇的filter继续写的,细心的朋友可以看到,过滤器是在拦截器之前执行的。

接下来,使用包含特地字符sb的url进行请求。http://localhost:8080/login?name=sb&phone=156532890870&password=123456

可以看到,因为包含特定的字符sb,成功在preHandle进行了拦截。这样,因为拦截成功了,自然也不会执行后续的postHandlle和afterCompletion。

四、多个拦截器

学习过滤器的时候,我们可以设置多个过滤器。拦截器前面也提到过了,可以有0-多个。接下来,我们再创建一个拦截器,代码直接复制第一个的,只看下执行的流程:

java 复制代码
package com.zhaojun.server.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Interceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器2处理中...");
        String queryString = request.getQueryString();
        if (queryString.contains("sb")) {
            System.out.println("拦截");
            return false;
        }
        System.out.println("放行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器2处理结束...");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("请求结束2...");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

相应的,需要在Config类中添加这个拦截器:

java 复制代码
package com.zhaojun.server.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/login");
        registry.addInterceptor(new Interceptor2());
    }
}

分别用不含有sb的url 和含有sb的url请求,执行流程如下:

可以看到一些规则,在这里也简单的总结下:

(1)当第一个拦截器没有在preHandle进行拦截的情况下,会顺序执行到第二个拦截器的preHandle。

(2)如果第二个拦截器也没有在preHandle拦截,那么接下来依次倒序执行postHandle和afterCompletion。

(3)如果第一个拦截器没有拦截,第二个拦截器拦截了,那么会直接执行第一个拦截器的afterCompletion。

(4)如果第一个拦截器拦截了,那么后续的拦截器也不会再执行。

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm