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)如果第一个拦截器拦截了,那么后续的拦截器也不会再执行。

相关推荐
ServBay5 小时前
打通 AI 编程本地运维边界,利用 MCP 协议简化环境与服务管理
后端·ai编程·mcp
程序员cxuan5 小时前
DeepSeek 杀入多模态,识图功能正式上线!
人工智能·后端·程序员
IT_陈寒8 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
用户395240998809 小时前
排坑日记:ASP.NET Core 中 "Required field is not provided" 验证错误全记录
后端
用户3521802454759 小时前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
用户83562907805110 小时前
使用 Python 自动化 PowerPoint 形状布局与格式设置
后端·python
Oneslide10 小时前
sudo免密权限配置不生效
后端
站大爷IP10 小时前
为什么Python不用var或let声明变量?
后端
赴星半途10 小时前
NestJS实战-创建AuthService
后端