如何定义Spring Boot过滤器

2023/05/11

1. 概述

在这个快速教程中,我们将探索如何在Spring Boot的帮助下定义自定义过滤器并指定它们的调用顺序。

2. 定义过滤器和调用顺序

让我们从创建两个过滤器开始:

  1. TransactionFilter:启动和提交事务
  2. RequestResponseLoggingFilter:记录请求和响应

为了创建过滤器,我们只需要实现Filter接口:

@Component
@Order(1)
public class TransactionFilter implements Filter {
    private final static Logger LOG = LoggerFactory.getLogger(TransactionFilter.class);

    @Override
    public void init(final FilterConfig filterConfig) {
        LOG.info("Initializing filter :{}", this);
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        LOG.info("Starting Transaction for req :{}", req.getRequestURI());
        chain.doFilter(request, response);
        LOG.info("Committing Transaction for req :{}", req.getRequestURI());
    }

    @Override
    public void destroy() {
        LOG.warn("Destructing filter :{}", this);
    }
}
@Component
@Order(2)
public class RequestResponseLoggingFilter implements Filter {
    private final static Logger LOG = LoggerFactory.getLogger(RequestResponseLoggingFilter.class);

    @Override
    public void init(final FilterConfig filterConfig) {
        LOG.info("Initializing filter :{}", this);
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        LOG.info("Logging Request  {} : {}", req.getMethod(), req.getRequestURI());
        chain.doFilter(request, response);
        LOG.info("Logging Response :{}", res.getContentType());
    }

    @Override
    public void destroy() {
        LOG.warn("Destructing filter :{}", this);
    }
}

为了让Spring识别过滤器,我们需要将其定义为带有@Component注解的bean。

此外,为了让过滤器以正确的顺序触发,我们需要使用@Order注解

2.1 使用URL模式过滤

在上面的示例中,我们的过滤器默认为应用程序中的所有URL注册。但是,有时我们可能希望过滤器仅适用于特定的URL模式。

在这种情况下,我们必须从过滤器类定义中删除@Component注解并使用FilterRegistrationBean注册过滤器

@Configuration
public class FilterConfig {

    // uncomment this and comment the @Component in the filter class definition to register only for a url pattern
    // @Bean
    public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter() {
        FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean = new FilterRegistrationBean<>();

        registrationBean.setFilter(new RequestResponseLoggingFilter());
        registrationBean.addUrlPatterns("/users/*");
        registrationBean.setOrder(2);

        return registrationBean;
    }
}

请注意,在这种情况下,我们需要使用setOrder()方法显式设置order属性。

现在过滤器将仅适用于匹配/users/*模式的路径。

要为过滤器设置URL模式,我们可以使用addUrlPatterns()或setUrlPatterns()方法

3. 一个简单的例子

现在让我们创建一个简单的端点并向其发送HTTP请求:

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping()
    public List<User> getAllUsers() {
        LOG.info("Fetching all the users");
        // ...
    }
}

当访问此端点时,控制台的日志如下:

23:57:22.414 [http-nio-8080-exec-1] INFO  [c.t.t.b.filters.TransactionFilter] >>> Starting Transaction for req :/users 
23:57:22.414 [http-nio-8080-exec-1] INFO  [c.t.t.b.f.RequestResponseLoggingFilter] >>> Logging Request  GET : /users 
23:57:22.426 [http-nio-8080-exec-1] INFO  [c.t.t.b.controller.UserController] >>> Fetching all the users 
23:57:22.465 [http-nio-8080-exec-1] INFO  [c.t.t.b.f.RequestResponseLoggingFilter] >>> Logging Response :application/json 
23:57:22.465 [http-nio-8080-exec-1] INFO  [c.t.t.b.filters.TransactionFilter] >>> Committing Transaction for req :/users 

可以看出我们的过滤器是以正确的顺序调用的。

4. 总结

在这篇简短的文章中,我们总结了如何在Spring Boot Webapp中定义自定义过滤器。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章