SpringBoot注冊(cè)FilterRegistrationBean相關(guān)情況講解
思路
- 首先編寫程序時(shí),或多或少會(huì)存在幾個(gè)固定的Filter,那么第一步就是為確定的那幾個(gè)Filter指定好順序。(通常情況下的使用場(chǎng)景是:你要將你現(xiàn)在編寫的項(xiàng)目打包成jar給別的項(xiàng)目使用)
- 其次程序確定的幾個(gè)Filter已經(jīng)編寫好了,那么需要將它們和不確定的那幾個(gè)放在一起進(jìn)行重新排序。
- 將排好序的Filter進(jìn)行注冊(cè)。
補(bǔ)充:FilterRegistrationBean的使用
@Bean
FilterRegistrationBean<AFilter> filterRegistrationBean() {
FilterRegistrationBean<AFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new AFilter());
return filterRegistrationBean;
}
手動(dòng)注冊(cè)代碼
先隨便定義幾個(gè)過(guò)濾器,后面?zhèn)溆?/p>
都一樣的,我復(fù)制了幾個(gè):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 的過(guò)濾器");
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";
}
}
已確定的過(guò)濾器注冊(cè)類
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
/**
* 已確定的過(guò)濾器排序
*/
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;
}
}
}
手動(dòng)注冊(cè)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 {
//可以通過(guò)這個(gè)BeanFactoryPostProcessor接口實(shí)現(xiàn)使某些過(guò)濾器失效的操作
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 過(guò)濾器失效。這應(yīng)該是通用的,如果有其他的過(guò)濾器想失效的,一樣操作即可。例如Spring Security中的一堆過(guò)濾器
將DefaultFilterRegister注冊(cè)成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() {
//正常的話應(yīng)該是: A(被失效) E B D C
DefaultFilterRegister defaultFilterRegister
= new DefaultFilterRegister()
.addFilterBefore(new DFilter(), CFilter.class)
.addFilterAfter(new EFilter(), AFilter.class);
return defaultFilterRegister.performRegister();
}
}以上便是手動(dòng)注冊(cè)Filter的全部代碼,同時(shí),如果該項(xiàng)目被打成jar包給其他項(xiàng)目使用時(shí),自定義DefaultFilterRegister這個(gè)Bean就可以實(shí)現(xiàn)在內(nèi)置的過(guò)濾器前面或者后面增加新的過(guò)濾器。
到此這篇關(guān)于SpringBoot注冊(cè)FilterRegistrationBean相關(guān)情況講解的文章就介紹到這了,更多相關(guān)SpringBoot注冊(cè)FilterRegistrationBean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于SpringSecurity簡(jiǎn)介以及和Shiro的區(qū)別
這篇文章主要介紹了關(guān)于SpringSecurity簡(jiǎn)介以及和Shiro的區(qū)別,在Java應(yīng)用安全領(lǐng)域,Spring Security會(huì)成為被首先推崇的解決方案,就像我們看到服務(wù)器就會(huì)聯(lián)想到Linux一樣順理成章,需要的朋友可以參考下2023-07-07
如何調(diào)用chatGPT實(shí)現(xiàn)代碼機(jī)器人
最近c(diǎn)hatGPT也是非常的火爆,相信大家都看到了,現(xiàn)在提供一種Java調(diào)用chatGPT的方法,我們主要通過(guò)兩個(gè)工具來(lái)實(shí)現(xiàn),一就是httpclient,二就是hutool,你覺(jué)得那種好理解你就用那種即可,今天通過(guò)本文給大家分享調(diào)用chatGPT實(shí)現(xiàn)代碼機(jī)器人,感興趣的朋友一起看看吧2022-12-12
Java IO流之原理分類與節(jié)點(diǎn)流文件操作詳解
流(Stream)是指一連串的數(shù)據(jù)(字符或字節(jié)),是以先進(jìn)先出的方式發(fā)送信息的通道,數(shù)據(jù)源發(fā)送的數(shù)據(jù)經(jīng)過(guò)這個(gè)通道到達(dá)目的地,按流向區(qū)分為輸入流和輸出流2021-10-10
如何使用Spring工具類動(dòng)態(tài)匹配url
這篇文章主要介紹了如何使用Spring工具類動(dòng)態(tài)匹配url,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Mybatis的parameterType造成線程阻塞問(wèn)題分析
這篇文章主要詳細(xì)分析了Mybatis的parameterType造成線程阻塞問(wèn)題,文中有詳細(xì)的解決方法,及相關(guān)的代碼示例,具有一定的參考價(jià)值,感興趣的朋友可以借鑒閱讀2023-06-06

