SpringBoot注册FilterRegistrationBean相关情况讲解

作者:愿做无知一猿 时间:2022-04-24 01:22:59 

思路

  • 首先编写程序时,或多或少会存在几个固定的Filter,那么第一步就是为确定的那几个Filter指定好顺序。(通常情况下的使用场景是:你要将你现在编写的项目打包成jar给别的项目使用)

  • 其次程序确定的几个Filter已经编写好了,那么需要将它们和不确定的那几个放在一起进行重新排序。

  • 将排好序的Filter进行注册。

补充:FilterRegistrationBean的使用

@Bean
FilterRegistrationBean<AFilter> filterRegistrationBean() {
   FilterRegistrationBean<AFilter> filterRegistrationBean = new FilterRegistrationBean<>();
   filterRegistrationBean.setFilter(new AFilter());
   return filterRegistrationBean;
}

手动注册代码

先随便定义几个过滤器,后面备用

都一样的,我复制了几个:AFilter、BFilter、CFilter、DFilter、EFilter

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
public class AFilter implements Filter {
   @Override
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       System.out.println("A 的过滤器");
       HttpServletRequest request = (HttpServletRequest) servletRequest;
       Map<String, String[]> parameterMap = request.getParameterMap();
       for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
           System.err.println("AAAA----->>>>>>  " + entry.getKey() + "----" + Arrays.toString(entry.getValue()));
       }
       filterChain.doFilter(servletRequest, servletResponse);
   }
}

调试用的controller

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
   @RequestMapping("/test")
   public Object test() {
       return "123";
   }
}

已确定的过滤器注册类

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
/**
* 已确定的过滤器排序
*/
public class InitFilterOrderRegistration {
   private static final int INITIAL_ORDER = 200;
   private static final int ORDER_STEP = 100;
   private final Map<String, Integer> filterToOrder = new HashMap<>();
   InitFilterOrderRegistration() {
       Step order = new Step(INITIAL_ORDER, ORDER_STEP);
       put(AFilter.class, order.next());
       put(BFilter.class, order.next());
       put(CFilter.class, order.next());
   }
   public Map<String, Integer> getOrderedFilterMap() {
       return this.filterToOrder;
   }
   void put(Class<? extends Filter> filter, int position) {
       String className = filter.getName();
       if (this.filterToOrder.containsKey(className)) {
           return;
       }
       this.filterToOrder.put(className, position);
   }
   Integer getOrder(Class<?> clazz) {
       while (clazz != null) {
           Integer result = this.filterToOrder.get(clazz.getName());
           if (result != null) {
               return result;
           }
           clazz = clazz.getSuperclass();
       }
       return null;
   }
   private static class Step {
       private int value;
       private final int stepSize;
       Step(int initialValue, int stepSize) {
           this.value = initialValue;
           this.stepSize = stepSize;
       }
       int next() {
           int value = this.value;
           this.value += this.stepSize;
           return value;
       }
   }
}

手动注册Filter的类

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.util.CollectionUtils;
import javax.servlet.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class DefaultFilterRegister implements BeanDefinitionRegistryPostProcessor {
   private final List<OrderedFilter> filters = new ArrayList<>();
   private final InitFilterOrderRegistration filterOrders = new InitFilterOrderRegistration();
   private final List<Filter> toRegister = new ArrayList<>();
   public DefaultFilterRegister performRegister() {
       Map<String, Integer> orderedFilterMap = filterOrders.getOrderedFilterMap();
       for (Map.Entry<String, Integer> entry : orderedFilterMap.entrySet()) {
           try {
               OrderedFilter orderedFilter = new OrderedFilter((Filter) Class.forName(entry.getKey()).newInstance(),
                       entry.getValue());
               this.filters.add(orderedFilter);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
       //排序并构造
       this.filters.sort(OrderComparator.INSTANCE);
       for (OrderedFilter filter : this.filters) {
           toRegister.add(filter.filter);
       }
       return this;
   }
   public DefaultFilterRegister addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
       return addFilterAtOffsetOf(filter, 1, afterFilter);
   }
   public DefaultFilterRegister addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) {
       return addFilterAtOffsetOf(filter, -1, beforeFilter);
   }
   private DefaultFilterRegister addFilterAtOffsetOf(Filter filter, int offset,
                                                     Class<? extends Filter> registeredFilter) {
       int order = this.filterOrders.getOrder(registeredFilter) + offset;
       this.filters.add(new OrderedFilter(filter, order));
       return this;
   }
   @Override
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
       if (CollectionUtils.isEmpty(toRegister)) {
           return;
       }
       for (Filter filter : toRegister) {
           BeanDefinitionBuilder beanDefinitionBuilder =
                   BeanDefinitionBuilder.genericBeanDefinition(filter.getClass());
           AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
           beanDefinition.setBeanClass(filter.getClass());
           beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
           registry.registerBeanDefinition(filter.getClass().getName(), beanDefinition);
       }
   }
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
       //可以通过这个BeanFactoryPostProcessor接口实现使某些过滤器失效的操作
       DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf;
       Arrays.stream(beanFactory.getBeanNamesForType(javax.servlet.Filter.class))
               .forEach(name -> {
                   //例如让A失效
                   if (name.equals(AFilter.class.getTypeName())) {
                       BeanDefinition definition = BeanDefinitionBuilder
                               .genericBeanDefinition(FilterRegistrationBean.class)
                               .setScope(BeanDefinition.SCOPE_SINGLETON)
                               .addConstructorArgReference(name)
                               .addConstructorArgValue(new ServletRegistrationBean[]{})
                               .addPropertyValue("enabled", false)
                               .getBeanDefinition();
                       beanFactory.registerBeanDefinition(name + "FilterRegistrationBean",
                               definition);
                   }
               });
   }
   private static final class OrderedFilter implements Ordered, Filter {
       private final Filter filter;
       private final int order;
       private OrderedFilter(Filter filter, int order) {
           this.filter = filter;
           this.order = order;
       }
       @Override
       public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
               throws IOException, ServletException {
           this.filter.doFilter(servletRequest, servletResponse, filterChain);
       }
       @Override
       public int getOrder() {
           return this.order;
       }
       @Override
       public String toString() {
           return "OrderedFilter{" + "filter=" + this.filter + ", order=" + this.order + '}';
       }
   }
}

注意代码里的 postProcessBeanFactory 方法,我在里面使 A 过滤器失效。这应该是通用的,如果有其他的过滤器想失效的,一样操作即可。例如Spring Security中的一堆过滤器

将DefaultFilterRegister注册成Bean

import com.kusch.filter.AFilter;
import com.kusch.filter.CFilter;
import com.kusch.filter.DefaultFilterRegister;
import com.kusch.filter.custom.DFilter;
import com.kusch.filter.custom.EFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class OrderedConfiguration {
   @Bean
   @ConditionalOnMissingBean
   DefaultFilterRegister defaultFilterRegister() {
       //正常的话应该是:  A(被失效)   E   B   D   C
       DefaultFilterRegister defaultFilterRegister
               = new DefaultFilterRegister()
               .addFilterBefore(new DFilter(), CFilter.class)
               .addFilterAfter(new EFilter(), AFilter.class);
       return defaultFilterRegister.performRegister();
   }
}

以上便是手动注册Filter的全部代码,同时,如果该项目被打成jar包给其他项目使用时,自定义DefaultFilterRegister这个Bean就可以实现在内置的过滤器前面或者后面增加新的过滤器。

来源:https://blog.csdn.net/qq_38397501/article/details/128706386

标签:SpringBoot,注册,FilterRegistrationBean
0
投稿

猜你喜欢

  • java中如何判断JSONObject是否存在某个Key

    2022-06-10 15:07:24
  • Spring Cloud Config 使用本地配置文件方式

    2021-06-03 03:17:53
  • C# 中如何利用lambda实现委托事件的挂接

    2022-02-06 03:18:00
  • C语言中求字符串长度的函数的几种实现方法

    2023-07-04 23:29:05
  • Java IO流和文件操作实现过程解析

    2022-03-10 02:08:13
  • Java 判断线程池所有任务是否执行完毕的操作

    2021-10-03 09:43:55
  • C语言字符串函数入门

    2021-07-22 17:10:15
  • spring boot结合Redis实现工具类的方法示例

    2023-05-12 09:47:46
  • JAVA IDEA 打开assert 设置方式

    2022-08-19 13:48:49
  • c# winform异步不卡界面的实现方法

    2021-10-03 22:27:33
  • Spring如何基于aop实现事务控制

    2021-07-21 11:26:06
  • c#通过xpath读取xml示例

    2023-07-16 01:31:05
  • Android实现的数字格式化用法示例

    2023-09-30 09:03:28
  • Spring mvc服务端数据校验实现流程详解

    2023-02-06 16:37:14
  • Android控件之TabHost用法实例分析

    2021-07-19 10:35:21
  • 微信跳一跳辅助Java代码实现

    2022-03-31 19:12:03
  • Java中的break和continue关键字的使用方法总结

    2022-07-13 11:50:46
  • Android中使用ShareSDK集成分享功能的实例代码

    2022-02-12 06:19:53
  • C# TrackBar拖动条改变滑块颜色

    2021-12-22 22:11:07
  • 实例详解Android自定义ProgressDialog进度条对话框的实现

    2023-02-18 08:32:40
  • asp之家 软件编程 m.aspxhome.com