前言
想根据过滤器 filter 来实现 sdk 的一些功能, 但是配置多个过滤器又给调用方带来了配置的复杂性。所以这里模仿 SpringSecurity 中的 DelegatingFilterProxy 和 FilterChainProxy 来实现了一个自定义的 FilterChain。源码参照 spring-boot-starter-security 中的源码, 相关代码位于 spring-security-web 包中
 实现
 1. 首先我们随意定义2个过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | package com.example.filterchain.filter;
  import javax.servlet.*; import java.io.IOException;
 
 
 
 
  public class AnonymousFilter implements Filter {     @Override     public void init(FilterConfig filterConfig) throws ServletException {         System.out.println("AnonymousFilter init...");     }
      @Override     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {         System.out.println("AnonymousFilter doFilter...");         chain.doFilter(request, response);     }
      @Override     public void destroy() {         System.out.println("AnonymousFilter destroy...");     } }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | package com.example.filterchain.filter;
  import javax.servlet.*; import java.io.IOException;
 
 
 
 
  public class FormAuthenticationFilter implements Filter {     @Override     public void init(FilterConfig filterConfig) throws ServletException {         System.out.println("FormAuthenticationFilter init...");     }
      @Override     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {         System.out.println("FormAuthenticationFilter doFilter...");         chain.doFilter(request, response);     }
      @Override     public void destroy() {         System.out.println("FormAuthenticationFilter destroy...");     } }
   | 
 
 2. 用枚举将过自定义滤器管理起来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | import org.springframework.objenesis.instantiator.util.ClassUtils;
  import javax.servlet.Filter;
 
 
 
 
  public enum DefaultFilter {
      anon(AnonymousFilter.class),     authc(FormAuthenticationFilter.class);
      private final Class<? extends Filter> filterClass;
      private DefaultFilter(Class<? extends Filter> filterClass) {         this.filterClass = filterClass;     }
      public Filter newInstance() {         return (Filter) ClassUtils.newInstance(this.filterClass);     } }
   | 
 
 3. 代理过滤器
代理过滤器也是 servlet 标准过滤器, 需要能够注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
   | package com.example.filterchain.filter;
  import lombok.extern.slf4j.Slf4j;
  import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.ArrayList; import java.util.List;
 
 
 
 
  @Slf4j public class FilterChainProxy implements Filter {
      private List<Filter> filters;
      @Override     public void init(FilterConfig filterConfig) throws ServletException {         this.filters = new ArrayList<>();         for (DefaultFilter defaultFilter : DefaultFilter.values()) {             this.filters.add(defaultFilter.newInstance());         }     }
      @Override     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {         HttpServletRequest httpServletRequest = (HttpServletRequest) request;         log.info("FilterChainProxy.doFilter.uri:{}", httpServletRequest.getRequestURI());         doFilterInternal(request, response, chain);     }
      private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {         List<Filter> filters = getFilters();
                   if (filters == null || filters.size() == 0) {             chain.doFilter(request, response);             return;         }
                   VirtualFilterChain vfc = new VirtualFilterChain(request, chain, filters);                  vfc.doFilter(request, response);     }
      public List<Filter> getFilters() {         return filters;     }
      public void setFilters(List<Filter> filters) {         this.filters = filters;     }
      private class VirtualFilterChain implements FilterChain{
                   private final FilterChain originalChain;                  private final List<Filter> additionalFilters;                  private final int size;                  private int currentPosition = 0;
          public VirtualFilterChain(ServletRequest request, FilterChain chain, List<Filter> additionalFilters) {             this.originalChain = chain;             this.additionalFilters = additionalFilters;             this.size = additionalFilters.size();         }
          @Override         public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
              if (currentPosition == size) {                                  originalChain.doFilter(request, response);             } else {                 currentPosition++;                                  Filter nextFilter = additionalFilters.get(currentPosition - 1);                 nextFilter.doFilter(request, response, this);             }         }     } }
   | 
 
 4. 注册过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | package com.example.filterchain.config;
  import com.example.filterchain.filter.FilterChainProxy; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered;
 
 
 
 
  @Configuration public class FilterConfig {
      @Bean     public FilterRegistrationBean filterChainProxy() {         FilterRegistrationBean<FilterChainProxy> filterRegistrationBean = new FilterRegistrationBean<>();         filterRegistrationBean.setFilter(new FilterChainProxy());         filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 100);         filterRegistrationBean.setName("filterChainProxy");         filterRegistrationBean.addUrlPatterns("/*");         filterRegistrationBean.setEnabled(true);         return filterRegistrationBean;     } }
   | 
 
 执行结果
1 2 3
   | 2021-03-28 14:55:40.405  INFO 11175 --- [nio-8080-exec-1] c.e.filterchain.filter.FilterChainProxy  : FilterChainProxy.doFilter.uri:/actuator/prometheus AnonymousFilter doFilter... FormAuthenticationFilter doFilter...
   | 
 
我们可以看到首先执行了我们的标准代理过滤器 FilterChainProxy, 然后执行自定义的过滤器链
 最后
本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。
 参考