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

相关推荐
silvamux_13 分钟前
Spring Boot 调用大模型 api 最小可跑教程
java·spring boot·后端
今年下半年16 分钟前
【Spring Boot 】通过 OpenFeign 请求第三方接口
java·spring boot·后端·openfeign
范什么特西25 分钟前
亲和路由(inspect)
java
她说可以呀28 分钟前
Docker 镜像的两种创建方式
java·分布式·docker
霸道流氓气质37 分钟前
AgentFlow 入门与实战:Task-Based 并发、EWMA 动态调度与四道门禁的 Java 生产级编排
java·开发语言
UrbanJazzerati1 小时前
AutoHotkey v2 零基础快速入门 Part 3 像素亮度检测完全指南
后端
浮链序1 小时前
Shopify 把 10 亿商品开放给任意 agent 了:我用零依赖 Python 撸了个带预算闸门的代购网关
后端·代码规范
愿得一猪蹄1 小时前
# Java线程池实战,别再new Thread了
java
ee又momo1 小时前
# 深入理解Java注解,从使用到自定义
java
Qlly1 小时前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端