Spring拦截器原理与实战详解

目录

拦截器:

拦截器与过滤器区别

下面是请求发出后的映射过程:

拦截器的入门案例:

第一步:创建一个java类,声明拦截器的bean,并实现HandlerInterceptor接口。

第二步:注册拦截器(不能只创建不使用吧!)

扫描的具体过程:

拦截器的参数;

拦截器链:


前言:当浏览器给我们发送一个请求的时候,请求先到达tomcat服务器,tomcat根据请求来确认这次请求该如何处理。拦截到了所有的请求,然后划分成了静态资源(html页面,CSS,JS等等),(tomcat服务器可以直接给我们)和动态资源,动态资源才是我们要处理的。动态资源不是直接进入到Cotroller层,而是先经过过滤器的筛选,不止一层,,之后才交给我们的处理器去做,中央控制器去会根据请求来判断进入到哪个controller层(将请求分发到具体的控制器当中)当controller执行完后,会返回给浏览器数据。而拦截器就是加在controller层前后的机制。

拦截器:

是一种动态拦截方法调用的机制,在SpringMvc中动态拦截控制器方法的执行。

作用:
++在指定的方法调用前后执行预先设定的代码++

++阻止原始方法的执行++

拦截器与过滤器区别

归属不同:Filter属于Servlet技术,Interceptor属于SpringMVc技术

拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVc的访问进行增强

原理:

拦截器拦截的是请求,可以在请求到达方法前后进行处理

Postman中localhost后面加的是接口地址,这个地址对应后端的一个方法

下面是请求发出后的映射过程:

复制代码
Postman请求: GET http://localhost:8080/api/users/info?id=1001
                    ↓
             DispatcherServlet (前端控制器)
                    ↓
         HandlerMapping (寻找对应的处理器)
                    ↓
             匹配到:@GetMapping("/info")
                    ↓
         HandlerAdapter (适配器,准备调用方法)
                    ↓
           UserController.getUserInfo(1001)
                    ↓
                返回响应

拦截器的入门案例:

第一步:创建一个java类,声明拦截器的bean,并实现HandlerInterceptor接口。

具体操作:

复制代码
// 使用 @Component 注解,将该类声明为一个Spring Bean
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    // 在请求到达Controller之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("LoginInterceptor preHandle...");
        // 返回true表示放行,false表示拦截
        return true; 
    }

    // 在Controller执行之后,视图渲染之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("LoginInterceptor postHandle...");
    }

    // 在整个请求完成之后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("LoginInterceptor afterCompletion...");
    }
}

第二步:注册拦截器(不能只创建不使用吧!)

创建一个配置类,实现WebMvcconfigurer接口,并重写addInterceptor方法,将上一步定义的拦截器bean添加到InterceptorRegistry中。重点:这个配置类需要被Spring管理,使用@Configuration注解,

具体操作:

复制代码
// 使用 @Configuration 注解,声明这是一个配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {

    // 自动注入我们定义好的拦截器Bean
    @Autowired
    private LoginInterceptor loginInterceptor;

    // 重写addInterceptors方法,进行注册
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,并配置拦截/放行的路径
        registry.addInterceptor(loginInterceptor) // 将拦截器Bean添加到注册中心
                .addPathPatterns("/**")          // 拦截所有请求路径
                .excludePathPatterns("/user/login", "/user/register"); // 放行登录和注册路径

扫描的具体过程:

Spring Boot在启动时,会扫描指定包(通常是主启动类所在包及其子包)下的所有类。它主要扫描两种东西:

  • 带有特定注解的类 :例如 @Component、@Configuration、@Service、@Controller 等。在我们的例子里,LoginInterceptor和WebConfig都被扫描到了。

  • 实现特定接口的类 :例如实现了WebMvcConfigurer接口的类。

  • 当扫描到LoginInterceptor上的@Component时,Spring容器会创建它的一个实例(一个Bean),并管理起来。

  • 当扫描到WebConfig上的@Configuration时,Spring会识别出它是一个配置类,并执行其内部定义好的配置逻辑,特别是重写的addInterceptors方法。

  • 在addInterceptors方法执行时,InterceptorRegistry(拦截器注册表)会拿到我们注入的loginInterceptor Bean,并将它注册到Spring MVC的内部拦截器链中。

最终,当一个请求(比如你在Postman中输入的地址)到达时,Spring MVC的分发器(DispatcherServlet)就会从这个拦截器链中依次调用匹配的拦截器,从而执行我们在LoginInterceptor中定义的preHandlepostHandle等逻辑。

拦截器的参数;

参数 使用场景 主要作用
request 所有方法 获取请求信息(头、参数、IP、URI等)
response preHandle, postHandle 控制响应(状态码、重定向、返回数据)
handler preHandle, postHandle, afterCompletion 获取目标方法信息(控制器、方法、注解)
modelAndView postHandle 操作模型数据和视图(仅页面请求)
exception afterCompletion 处理异常信息

拦截器链:

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

执行过程:

最后给大推荐如果您是计算机领域(AI / 大数据 / 网络 / 软件工程等)的研究者,近期有成果想投稿发表,这几个高认可度的国际会议可以参考(均支持 EI/SCOPUS 检索):

第七届计算机信息与大数据应用会议:

https://ais.cn/u/QnaAJz

第九届先进算法与控制工程会议:

https://ais.cn/u/BFfyuq

相关推荐
皮皮林5517 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
顺风尿一寸11 小时前
从 Java NIO poll 到 Linux 内核 poll:一次系统调用的完整旅程
java
程途知微11 小时前
JVM运行时数据区各区域作用与溢出原理
java
华仔啊13 小时前
为啥不用 MP 的 saveOrUpdateBatch?MySQL 一条 SQL 批量增改才是最优解
java·后端
xiaoye201816 小时前
Lettuce连接模型、命令执行、Pipeline 浅析
java
beata19 小时前
Java基础-18:Java开发中的常用设计模式:深入解析与实战应用
java·后端
Seven9719 小时前
剑指offer-81、⼆叉搜索树的最近公共祖先
java
舒一笑2 天前
程序员效率神器:一文掌握 tmux(服务器开发必备工具)
运维·后端·程序员
雨中飘荡的记忆2 天前
保证金系统入门到实战
java·后端
Nyarlathotep01132 天前
Java内存模型
java