【SpringBoot】FilterRegistrationBean一次只能注册一个Filter,那在Filter个数不确定的情况下如何注册呢,那便是需要手动注册过滤器

思路

  1. 首先编写程序时,或多或少会存在几个固定的Filter,那么第一步就是为确定的那几个Filter指定好顺序。(通常情况下的使用场景是:你要将你现在编写的项目打包成jar给别的项目使用)
  2. 其次程序确定的几个Filter已经编写好了,那么需要将它们和不确定的那几个放在一起进行重新排序。
  3. 将排好序的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就可以实现在内置的过滤器前面或者后面增加新的过滤器

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值