在这篇文章中,我们将探讨如何在 SpringBoot 中添加过滤器,以及在 SpringBoot 中配置这些过滤器的选项有哪些。

如何在 SpringBoot 中添加过滤器

在开发中,过滤器用于对客户端的请求或者客户端的响应过滤。SpringBoot 提供了几个选项可以在 SpringBoot 应用程序中注册自定义过滤器。借助过滤器,我们可以执行以下操作。

  • 在控制器执行之前过滤
  • 在数据相应客户端之前过滤

这是一个示例代码,概述了一个简单的 Servlet 过滤器。

@Component
public class MyFilter implements Filter {
   @Override
   public void destroy() {}

   @Override
   public void doFilter
      (ServletRequest request, ServletResponse response, FilterChain filterchain) 
      throws IOException, ServletException {
          
      }

   @Override
   public void init(FilterConfig filterconfig) throws ServletException {}
}
让我们看看在 SpringBoot 应用程序中添加过滤器有哪些选项。

1. SpringBoot 过滤器的执行顺序

在SpringBoot 过滤器中可以使用@Order注解来决定过滤器的执行顺序。例如,有两个过滤器:

@Component
@Order(1)
public class CustomFirstFilter implements Filter {

}

@Component
@Order(2)
public class CustomSecondFilter implements Filter {

}
CustomFirstFilter 将在 CustomSecondFilter 之前运行。数字越小,优先级越高。

2. 基于 URL Pattern 的过滤器

在某些情况下,可能只想拦截某个特定的url地址,比如/admin/xxxx格式的地址,这个可以作为后台登录地址的拦截,判断用户是否登录了,完整实现,可以参考 SpringBoot 过滤器实现用户登录 一章。

要运行 URL 格式匹配的过滤器,我们可以使用 FilterRegistrationBean。不要对过滤器类使用 @Component 注解,而是使用 FilterRegistrationBean注册过滤器。

public class AdminUrlFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("########## 初始化自定义过滤器 ##########");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        System.out.println("此过滤器仅在为 /admin 资源映射请求时调用");

        //调用下一个过滤器
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}
使用 FilterRegistrationBean注册自定义过滤器。
@Configuration
public class AdminUrlFilterConfig {

    @Bean
    public FilterRegistrationBean< AdminUrlFilter > filterRegistrationBean() {
        FilterRegistrationBean < AdminUrlFilter > registrationBean = new FilterRegistrationBean();
        AdminUrlFilter adminUrlFilter = new AdminUrlFilter();

        registrationBean.setFilter(adminUrlFilter);
        registrationBean.addUrlPatterns("/admin/*");//后台登录地址拦截
        registrationBean.setOrder(2);
        return registrationBean;
    }

}

3. OncePerRequestFilter

OncePerRequestFilter过滤器基类旨在保证在任何 servlet 容器上每次请求只执行一次。您还可以选择基于 URL 模式对其进行配置。

这个过滤器在处理 Spring 安全性时很有帮助,我们希望确保少数过滤器只执行一次。

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class MyFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response,
        FilterChain filterChain)
    throws ServletException, IOException {

        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}

4. Servlet @WebFilter 注解

如果您喜欢使用 Servlet 3.0 注解,我们可以选择在 SpringBoot 中为过滤器使用 @WebFilter 注解。 以下是使用@WebFilter 注解定义过滤器例子:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/greeting")
public class GreetingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter for greeting project");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}