SpringBoot - OncePerRequestFilter的使用场景

OncePerRequestFilter是Spring提供的一种过滤器实现,确保外部请求只执行一次过滤逻辑,避免服务器内部forward导致的重复过滤。本文介绍了过滤器的基本概念,OncePerRequestFilter的工作原理,以及如何在实际项目中使用它来处理JWT认证。同时,展示了如何通过配置使其在多过滤器环境中按指定顺序执行。

写在前面

OncePerRequestFilter类是一个实现了javax.servlet.Filter原生接口的抽象类。OncePerRequestFilter可以保证一次外部请求,只执行一次过滤方法,对于服务器内部之间的forward等请求,不会再次执行过滤方法。

什么是过滤器

在这里插入图片描述
在讲解"OncePerRequestFilter"前,我们先看一下过滤器是什么?

A. 过滤器在WEB应用启动时初始化一次, 在WEB应用停止时销毁;
B. 可以对请求的URL进行过滤, 对敏感词过滤;
C. 过滤器将处理逻辑挡在拦截器的外面;
D. 过滤器实现的是 javax.servlet.Filter原生接口,过滤器是SERVLET 规范的一部分;
E. 过滤器在请求进入WEB容器后,到达SERVLET之前进行过滤器的逻辑处理;
F. 过滤器依赖WEB容器,也会被多次执行。
G. 过滤器的作用就是在业务逻辑执行前/后对请求和响应进行相应的处理,如果能配合HttpServletRequestWrapper和HttpServletResponseWrapper使用更加完美。

什么是单次过滤器

OncePerRequestFilter类是一个实现了javax.servlet.Filter原生接口的抽象类。OncePerRequestFilter可以保证一次外部请求,只执行一次过滤方法,对于服务器内部之间的forward等请求,不会再次执行过滤方法。

使用场景

OncePerRequestFilter的主要目的是为了兼容不同的WEB容器,因为Servlet版本不同,执行的过程也不同,其实不是所有的容器一次请求只过滤一次。

源码分析

public abstract class OncePerRequestFilter extends GenericFilterBean {
   
   
     
    ...
    
    public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
   
   
        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
   
   
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            HttpServletResponse httpResponse = (HttpServletResponse)response;
            
            // 获取是否执行过滤方法的一个属性KEY,作为是否执行过滤方法的一个标记
            
<think>好的,我现在需要回答用户关于Spring BootOncePerRequestFilter与@GetMapping的关系及用法的问题。首先,我得明确这两个概念各自的作用和它们在Spring框架中的位置。 OncePerRequestFilterSpring中的一个过滤器基类,它的主要作用是确保每个请求只会被过滤一次,即使请求经过多个过滤器链。这对于需要保证单次过滤逻辑的情况非常有用,比如安全验证或日志记录。而@GetMapping是Spring MVC中处理HTTP GET请求的注解,用于将方法映射到特定的URL路径上。 接下来,我需要理解用户的问题核心:他们想知道这两个组件之间的区别、联系以及各自的使用场景。可能用户在使用过滤器时遇到了问题,或者想了解如何结合使用过滤器和控制器方法。 首先,我应该回顾OncePerRequestFilter的特点。根据引用[2],在Spring Boot使用Filters实现请求过滤和预处理,OncePerRequestFilter可以确保每个请求只被处理一次,避免多次执行过滤逻辑。这在需要预处理请求或后处理响应时非常有用,比如身份验证、日志记录、设置请求属性等。 然后是@GetMapping,引用[3]提到,它是@RequestMapping的派生注解,专门处理GET请求,简化了代码。控制器中的方法使用@GetMapping来响应特定的GET请求,处理业务逻辑并返回视图或数据。 两者的区别主要在于职责不同。过滤器属于Servlet层面的组件,处理请求的预处理和响应后处理;而@GetMapping属于MVC控制器,负责具体的业务处理。它们之间的联系在于过滤器会在请求到达控制器之前执行,因此可以影响或预处理即将进入@GetMapping方法的数据。 接下来,我需要考虑用户可能需要的具体使用场景。例如,OncePerRequestFilter可以用于记录请求日志、检查权限头、设置语言环境等。而@GetMapping则用于定义具体的业务端点,如获取用户信息或处理表单提交。 结合用户提供的引用,特别是引用[2]关于过滤器的配置,我需要说明如何在Spring Boot中实现OncePerRequestFilter,并如何与控制器中的@GetMapping协同工作。例如,一个权限验证的过滤器可能会在请求到达@GetMapping方法前检查用户的权限,若权限不足则直接返回错误响应,否则允许请求继续到控制器处理。 此外,用户可能想知道如何配置过滤器的顺序,或者如何处理跨过滤器和控制器的数据传递。比如,在过滤器中设置请求属性,然后在@GetMapping方法中获取这些属性。同时,需要确保过滤器的执行顺序正确,以免影响业务逻辑。 最后,总结两者的关系和各自的最佳实践,帮助用户明确何时使用过滤器,何时使用控制器注解,以及它们如何协同工作来构建完整的请求处理流程。</think>### Spring BootOncePerRequestFilter与@GetMapping的关系及用法 #### 1. **基本概念与职责区别** - **OncePerRequestFilter** 是Spring框架提供的过滤器基类,确保每个请求**仅被过滤一次**,常用于请求预处理或响应后处理(如日志记录、权限校验、请求头处理)[^2]。 示例代码: ```java public class LogFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 记录请求日志 System.out.println("Request URL: " + request.getRequestURL()); filterChain.doFilter(request, response); // 继续执行后续过滤器或控制器 } } ``` - **@GetMapping** 属于Spring MVC控制器注解,用于将**HTTP GET请求**映射到特定方法,处理业务逻辑并返回响应[^3]。 示例代码: ```java @RestController public class UserController { @GetMapping("/user") public String getUser() { return "User Details"; } } ``` #### 2. **执行顺序与协作关系** 1. **过滤器先于控制器执行** 请求到达Spring Boot应用后,先经过过滤器链(如`OncePerRequestFilter`),再进入`@GetMapping`标注的控制器方法[^2]。 2. **数据传递** 过滤器可通过`request.setAttribute()`设置属性,控制器通过`@RequestAttribute`获取: ```java // 过滤器中设置属性 request.setAttribute("traceId", UUID.randomUUID().toString()); // 控制器中获取属性 @GetMapping("/data") public String getData(@RequestAttribute("traceId") String traceId) { return "Trace ID: " + traceId; } ``` #### 3. **典型使用场景对比** | 组件 | 使用场景 | 示例 | |---------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------| | OncePerRequestFilter | 全局性请求处理(如权限验证、请求日志、跨域处理) | 在过滤器中检查JWT令牌,若无效则直接返回401响应 | | @GetMapping | 定义具体业务端点(如获取数据、提交表单) | 处理`/api/users`的GET请求,返回用户列表数据[^3] | #### 4. **配置与注册方式** - **过滤器配置** 需通过`FilterRegistrationBean`注册并指定顺序或URL匹配规则: ```java @Bean public FilterRegistrationBean<LogFilter> loggingFilter() { FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new LogFilter()); registration.addUrlPatterns("/*"); // 匹配所有URL registration.setOrder(1); // 执行顺序 return registration; } ``` - **@GetMapping配置** 直接标注在控制器方法上,支持路径参数、请求参数等: ```java @GetMapping("/user/{id}") public User getUser(@PathVariable Long id, @RequestParam String type) { // 根据id和type查询用户 } ``` #### 5. **性能与注意事项** - **过滤器性能影响** 若过滤器链过长或逻辑复杂,可能增加请求延迟。建议在过滤器中避免阻塞操作(如同步数据库查询)。 - **控制器方法优化** 结合`@Valid`进行参数校验(引用[^4]),或使用DTO直接绑定请求参数: ```java @PostMapping("/user") public ResponseEntity<?> createUser(@Valid @RequestBody UserDTO user) { // 处理校验通过的请求 } ``` --- ### § 相关问题 § 1. **如何确保过滤器仅对特定URL生效?** (提示:通过`FilterRegistrationBean`设置`addUrlPatterns`) 2. **@GetMapping和@PostMapping在参数处理上有何不同?** (提示:GET请求参数通过URL或`@RequestParam`接收,POST请求常用`@RequestBody`) 3. **如何全局捕获过滤器抛出的异常?** (提示:结合`@ControllerAdvice`和`@ExceptionHandler`) 4. **Spring Boot中如何实现请求参数的自动校验?** (参考引用[^4]中的`@Valid`用法)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cloneme01

谢谢您的支持与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值