SpringBoot注冊FilterRegistrationBean相關(guān)情況講解
思路
- 首先編寫程序時,或多或少會存在幾個固定的Filter,那么第一步就是為確定的那幾個Filter指定好順序。(通常情況下的使用場景是:你要將你現(xiàn)在編寫的項目打包成jar給別的項目使用)
- 其次程序確定的幾個Filter已經(jīng)編寫好了,那么需要將它們和不確定的那幾個放在一起進行重新排序。
- 將排好序的Filter進行注冊。
補充:FilterRegistrationBean的使用
@Bean FilterRegistrationBean<AFilter> filterRegistrationBean() { FilterRegistrationBean<AFilter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new AFilter()); return filterRegistrationBean; }
手動注冊代碼
先隨便定義幾個過濾器,后面?zhèn)溆?/p>
都一樣的,我復制了幾個: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); } }
調(diào)試用的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(); } } //排序并構(gòu)造 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接口實現(xiàn)使某些過濾器失效的操作 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就可以實現(xiàn)在內(nèi)置的過濾器前面或者后面增加新的過濾器。
到此這篇關(guān)于SpringBoot注冊FilterRegistrationBean相關(guān)情況講解的文章就介紹到這了,更多相關(guān)SpringBoot注冊FilterRegistrationBean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于SpringSecurity簡介以及和Shiro的區(qū)別
這篇文章主要介紹了關(guān)于SpringSecurity簡介以及和Shiro的區(qū)別,在Java應用安全領(lǐng)域,Spring Security會成為被首先推崇的解決方案,就像我們看到服務器就會聯(lián)想到Linux一樣順理成章,需要的朋友可以參考下2023-07-07如何調(diào)用chatGPT實現(xiàn)代碼機器人
最近chatGPT也是非常的火爆,相信大家都看到了,現(xiàn)在提供一種Java調(diào)用chatGPT的方法,我們主要通過兩個工具來實現(xiàn),一就是httpclient,二就是hutool,你覺得那種好理解你就用那種即可,今天通過本文給大家分享調(diào)用chatGPT實現(xiàn)代碼機器人,感興趣的朋友一起看看吧2022-12-12Mybatis的parameterType造成線程阻塞問題分析
這篇文章主要詳細分析了Mybatis的parameterType造成線程阻塞問題,文中有詳細的解決方法,及相關(guān)的代碼示例,具有一定的參考價值,感興趣的朋友可以借鑒閱讀2023-06-06