• springboot 2.1.3.RELEASE添加filter,servlet源码学习


    Servlet规范中,通过ServeltContext来注册Filter、Servlet,这里分析Filter,Servlet是相同逻辑

    springboot2.0中,我们通过

    FilterRegistrationBean将指定得filter来实现ServeltContext注册filter

    FilterRegistrationBean的实例化过程
    
    public FilterRegistrationBean(T filter, ServletRegistrationBean... servletRegistrationBeans) {
            super(servletRegistrationBeans);
            Assert.notNull(filter, "Filter must not be null");
            this.filter = filter;
    }
    
    super的实例化
    AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) {
            Assert.notNull(servletRegistrationBeans, "ServletRegistrationBeans must not be null");
            Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans);
    }
    

    可知FilterRegistrationBean得实例化过程就是将Filter保存到servletRegistrationBeans(一个set)中

    再分析FilterRegistrationBean类

    FilterRegistrationBean的父类是一个ServletContextInitializer,他有一个方法onStartup(ServletContext servletContext)
    其结果最终会调用
    servletContext.addFilter(this.getOrDeduceName(filter), filter)
    现在看看ServletContextInitializer.onStartup的调用地方
    springboot启动
    new SpringApplication(XXApplication.class).run(XXApplication.class,args)
    调用
    refreshContext(context); -> refresh(context); -> ((AbstractApplicationContext) applicationContext).refresh();
    -> ServletWebServerApplicationContext.onRefresh(); -> createWebServer();
    
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
    	ServletWebServerFactory factory = getWebServerFactory();
    	this.webServer = factory.getWebServer(getSelfInitializer());
    }
    

    再分析getSelfInitializer方法

    prepareWebApplicationContext(servletContext);
    		registerApplicationScope(servletContext);
    		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);
    		for (ServletContextInitializer beans :getServletContextInitializerBeans()) {
                  //调用ServletContextInitializer的onStartup方法
                  beans.onStartup(servletContext); 
    }
    -> getServletContextInitializerBeans()
    -> new ServletContextInitializerBeans(getBeanFactory())
    -> addAdaptableBeans(beanFactory)
    

     

    addAdaptableBeans(ListableBeanFactory beanFactory) 代码如下:
    MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
    //将servlet类的bean包装为ServletRegistrationBean
    addAsRegistrationBean(beanFactory, Servlet.class,new ServletRegistrationBeanAdapter(multipartConfig));
    //将Filter的bean包装为FilterRegistrationBean
    addAsRegistrationBean(beanFactory, Filter.class,new FilterRegistrationBeanAdapter());
    for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {		
      addAsRegistrationBean(beanFactory, EventListener.class,(Class<EventListener>) listenerType,new ServletListenerRegistrationBeanAdapter()); }

     这里提一下,如果Servlet的bean实例名为dispatcherServlet,且该实例在seen集合中(seen集合为自定义配置的实例,通过ServletContextInitializerBeans.addServletContextInitializerBean入口可以查看源码),则设置默认值为  /

    String url = (totalNumberOfSourceBeans != 1) ? "/" + name + "/" : "/";
    if (name.equals(DISPATCHER_SERVLET_NAME)) {
    	url = "/"; // always map the main dispatcherServlet to "/"
    }
    ServletRegistrationBean<Servlet> bean = new ServletRegistrationBean<>(source,url);	
    bean.setName(name); bean.setMultipartConfig(this.multipartConfig); return bean;

     

    总结:springboot启动时,会将所有的 FilterRegistrationBean、ServletRegistrationBean以及被spring管理的Servlet和Filter的实例,通过ServletContext注册Servlet以及Filter

    如果不希望filter自动注册,可以通过以下方式:

     @Bean
        public FilterRegistrationBean registration(@Qualifier("loginFilter") LoginFilter loginFilter) {
            FilterRegistrationBean registration = new FilterRegistrationBean(loginFilter);
            registration.setEnabled(false);
            return registration;
        }

     

     

     
    
    
  • 相关阅读:
    Firemonkey 控件设定字型属性及颜色
    ListView 使用 LiveBindings 显示超过 200 条记录
    Firemonkey ListView 获取项目右方「>」(Accessory) 事件
    XE7 Update 1 选 iOS 8.1 SDK 发布 iPhone 3GS 实机测试
    Firemonkey Bitmap 设定像素颜色 Pixel
    Firemonkey 移动平台 Form 显示使用 ShowModal 范例
    XE7 提交 App(iOS 8)提示「does not contain the correct beta entitlement」问题修复
    XE7 Android 中使用 MessageDlg 范例
    导出 XE6 预设 Android Style (*.style) 档案
    修正 Memo 設定為 ReadOnly 後, 無法有複製的功能
  • 原文地址:https://www.cnblogs.com/jaxlove-it/p/10564683.html
Copyright © 2020-2023  润新知