springboot 创建自定义filter 非常规写法

mac2026-02-19  11

先来一个很普通的例子, springBoot创建自定义filter

public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("加载进来了"); chain.doFilter(request,response); } @Override public void destroy() { } }

然后创建一个bean 将MyFilter注册到FilterRegistrationBean中

@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean(new MyFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.setName("myFilter"); return filterRegistrationBean; }

然后随便访问一个路径,即可看到 “加载进来了” 打印信息 具体的实现过程网上有很多了,这里不再赘述

然后来一个非常规的简化写法,自定义filter保持不变,bean的写法改变如下

@Bean public MyFilter myFilter(){ return new MyFilter(); }

再随便访问一个路径, 发现filter依然生效,显然是智能的springboot帮我们做了不少工作 这里简要的贴出相关源码 以做笔记

无论是通过 继承SpringBootServletInitializer 还是通过 SpringApplication.run() 的方式加载springboot, 都会初始化AnnotationConfigServletWebServerApplicationContext 其父类是ServletWebServerApplicationContext

@Override //org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh //最终会执行这段代码 protected void onRefresh() { super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { ServletWebServerFactory factory = getWebServerFactory(); this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { //关键是这句,做一些初始化的工作 getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); } private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() { return this::selfInitialize; } private void selfInitialize(ServletContext servletContext) throws ServletException { prepareWebApplicationContext(servletContext); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes( beanFactory); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, getServletContext()); existingScopes.restore(); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, getServletContext()); //关键代码, 获取需要做初始化的bean进行处理 for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); } } //这个获取初始化bean的操作最终交给了ServletContextInitializerBeans处理 protected Collection<ServletContextInitializer> getServletContextInitializerBeans() { return new ServletContextInitializerBeans(getBeanFactory()); }

接下来看ServletContextInitializerBeans 的重要代码

//可以看出,此类最终要输出 ServletContextInitializer的集合 //也就是说需要将相关的bean 包装成ServletContextInitializer的子类 //而刚好RegistrationBean也实现了ServletContextInitializer接口,似乎快水落石出了 public class ServletContextInitializerBeans extends AbstractCollection<ServletContextInitializer> //构造方法 public ServletContextInitializerBeans(ListableBeanFactory beanFactory) { this.initializers = new LinkedMultiValueMap<>(); addServletContextInitializerBeans(beanFactory); //重点看这里,使用适配的方式对beanFactory中的bean进行处理 addAdaptableBeans(beanFactory); List<ServletContextInitializer> sortedInitializers = new ArrayList<>(); this.initializers.values().forEach((contextInitializers) -> { AnnotationAwareOrderComparator.sort(contextInitializers); sortedInitializers.addAll(contextInitializers); }); this.sortedList = Collections.unmodifiableList(sortedInitializers); } private void addAdaptableBeans(ListableBeanFactory beanFactory) { MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory); //获取bean中所有的Servlet类,创建ServletRegistrationBeanAdapter适配器进行处理 addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig)); //同上 处理Filter addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter()); //处理相关的EventListener,具体查看ServletListenerRegistrationBean for (Class<?> listenerType : ServletListenerRegistrationBean .getSupportedTypes()) { addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType, new ServletListenerRegistrationBeanAdapter()); } }

到这里基本可以结束了,通过以上源码可以了解 springBoot 会筛选出bean中的 filter、servlet、EventListener 对象,包装成相应的RegistrationBean进行处理 当然了里面的相关属性也是默认的,如果需要自定义 还是得自己创建RegistrationBean

最新回复(0)