Spring中的拦截器

简介: Spring中的拦截器

基本概念

在web开发中,拦截器是经常用到的功能。它可以帮我们预先设置数据以及统计方法的执行效率等等。

Spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor。

HandlerInterceptor拦截器

HandlerInterceptor是SpringMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。其工作原理是当请求来时先进行预处理,如下:

通过HandlerInterceptor实现打印请求开始和结束的日志,代码如下:

引入相关依赖:

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

拦截器:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class EasyLogControllerInterceptor implements HandlerInterceptor {
    /**
     * 在controller调用之前执行
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        log.info(request.getRequestURI() + "开始执行");
        return true;
    }
    /**
     * 在controller调用中执行
     */
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }
    /**
     * 在controller调用后执行
     */
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        log.info(request.getRequestURI() + "执行结束");
    }
}

controller:

@GetMapping(value = "/test/user")
public String testUser() {
    log.info("test");
    return "string";
}

配置类:

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class IntercepterConfig implements WebMvcConfigurer {
    private final EasyLogControllerInterceptor easyLogControllerInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //addPathPatterns用于添加拦截路径
        //excludePathPatterns用于添加不拦截的路径
        registry.addInterceptor(easyLogControllerInterceptor).addPathPatterns("/test/user");
    }
    //此方法用于配置静态资源路径
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/my/");
    }
}

输出结果:

2023-02-20 21:07:10.681 c.x.d.c.EasyLogControllerInterceptor     : /test/user开始执行
2023-02-20 21:07:10.688 c.xhy.demo01.controller.HelloController  : test
2023-02-20 21:07:0.714 c.x.d.c.EasyLogControllerInterceptor     : /test/user执行结束

HandlerInterceptor讲解

实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法即可。

下面就是HandlerInterceptorAdapter的代码,可以看到一个方法只是默认返回true,另外两个是空方法:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        return true;
    }
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    }
}

这三个方法都是干什么的,有什么作用,什么时候调用,不同的拦截器之间是怎样的调用顺序呢?

看图前首先要先了解下SpringMVC的执行原理

1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配到DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.

2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。

3、将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用

4、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet

5、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View

6、Dispatcher通过model解析出ModelAndView()中的参数进行解析,最终展现出完整的view并返回给客户端

请求–前端控制器–处理器–处理器适配器–试图对象–前端控制器–视图解析器

这还得参考一下DispatcherServlet的doDispatch方法:

代码有点长,但是它封装了SpringMVC处理请求的整个过程。首先根据请求找到对应的HandlerExecutionChain,它包含了处理请求的handler和所有的HandlerInterceptor拦截器;然后在调用hander之前分别调用每个HandlerInterceptor拦截器的preHandle方法,若有一个拦截器返回false,则会调用triggerAfterCompletion方法,并且立即返回不再往下执行;若所有的拦截器全部返回true并且没有出现异常,则调用handler返回ModelAndView对象;再然后分别调用每个拦截器的postHandle方法;最后即使是之前的步骤抛出了异常,也会执行triggerAfterCompletion方法。

MethodInterceptor拦截器

MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法

具体实现可看:

Spring boot中通过Aop和拦截器实现自定义注解

二者的区别

上面的两种拦截器都能起到拦截的效果,但是他们拦截的目标不一样,实现的机制不同,所以有的时候适用不同的场景。

HandlerInterceptoer拦截的是请求地址,所以针对请求地址做一些验证、预处理等操作比较合适。当你需要统计请求的响应时间时,MethodInterceptor将不太容易做到,因为它可能跨越很多方法或者只涉及到已经定义好的方法中一部分代码。MethodInterceptor利用的是AOP的实现机制,在本文中只说明了使用方式,关于原理和机制方面介绍的比较少,因为要说清楚这些需要讲出AOP的相当一部分内容。在对一些普通的方法上的拦截HandlerInterceptoer就无能为力了,这时候只能利用AOP的MethodInterceptor。

另外,还有一个跟拦截器类似的东西----Filter。Filter是Servlet规范规定的,不属于Spring框架,也是用于请求的拦截。但是它适合更粗粒度的拦截,在请求前后做一些编解码处理、日志记录等。而拦截器则可以提供更细粒度的,更加灵活的,针对某些请求、某些方法的组合的解决方案。

另外,用过人人网的ROSE框架的人都会非常喜欢它的拦截器功能。因为它实现了全注解的方式,只要在类的名字上加上拦截器的注解即表示这是一个拦截器。而使用这个拦截器的方法或者controller也只需在方法或controller的上面加上这个拦截器的注解。其实这是一个关注点的转变,spring的切面控制在配置文件中,配置文件关注哪些地方需要拦截。而在ROSE中,则是在需要拦截的地方关注我要被谁拦截。


目录
相关文章
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
28 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
3月前
|
前端开发 JavaScript Java
Spring Boot中使用拦截器
本节主要介绍了 Spring Boot 中拦截器的使用,从拦截器的创建、配置,到拦截器对静态资源的影响,都做了详细的分析。Spring Boot 2.0 之后拦截器的配置支持两种方式,可以根据实际情况选择不同的配置方式。最后结合实际中的使用,举了两个常用的场景,希望读者能够认真消化,掌握拦截器的使用。
|
4月前
|
监控 前端开发 Java
Spring Boot中的拦截器配置
Spring Boot中的拦截器配置
|
5月前
|
监控 前端开发 Java
Spring Boot中的拦截器配置
Spring Boot中的拦截器配置
|
6月前
|
前端开发 Java 程序员
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
110 1
|
5月前
|
前端开发 JavaScript Java
【Spring Boot】 深入理解Spring Boot拦截器:自定义设计与实现全攻略
【Spring Boot】 深入理解Spring Boot拦截器:自定义设计与实现全攻略
90 0
|
6月前
|
前端开发 Java Spring
[AIGC] Spring Interceptor 拦截器详解
[AIGC] Spring Interceptor 拦截器详解
|
6月前
|
前端开发 Java 数据安全/隐私保护
Spring Boot使用拦截器:概念与实战
【4月更文挑战第29天】拦截器(Interceptors)在Spring Boot应用中常用于在请求处理的前后执行特定的代码,如日志记录、认证校验、权限控制等。本篇博客将详细介绍Spring Boot中拦截器的概念及其实战应用,帮助开发者理解和利用拦截器来增强应用的功能。
103 0
|
6月前
|
缓存 前端开发 Java
【Spring底层原理高级进阶】轻松掌握 Spring MVC 的拦截器机制:深入理解 HandlerInterceptor 接口和其实现类的用法
【Spring底层原理高级进阶】轻松掌握 Spring MVC 的拦截器机制:深入理解 HandlerInterceptor 接口和其实现类的用法
|
6月前
spring-state-machine拦截器
spring-state-machine拦截器
50 0
下一篇
无影云桌面