zoukankan      html  css  js  c++  java
  • 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;
        }

     

     

     
    
    
  • 相关阅读:
    hdu2222 AC自动机入门
    bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习
    【NOI2014】起床困难综合症 贪心
    bzoj1822: [JSOI2010]Frozen Nova 冷冻波网络流
    洛谷3767 膜法 带权并查集+分治
    NOI2015品酒大会 后缀数组
    NOI2015程序自动分析 并查集
    NOI2015软件包管理器 树剖线段树
    51nod1244 欧拉函数之和 杜教筛
    51nod1244 莫比乌斯函数之和 杜教筛
  • 原文地址:https://www.cnblogs.com/jaxlove-it/p/10564683.html
Copyright © 2011-2022 走看看