zoukankan      html  css  js  c++  java
  • 配置嵌入式Servlet容器

    一、如何定制和修改Servlet容器的相关配置

      1)修改server有关的配置(ServerProperties)

    server.port=8081
    server.context‐path=/crud
    server.tomcat.uri‐encoding=UTF‐8

      2)EmbeddedServletContainerCustomizer

    @Bean //一定要将这个定制器加入到容器中
    public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
      return new EmbeddedServletContainerCustomizer() {
        //定制嵌入式的Servlet容器相关的规则
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
          container.setPort(8081);
        }
      };
    }

    ServerProperties、EmbeddedServletContainerCustomizer定制器怎么就帮我们修改了Servlet容器的配置呢

    容器中导入了EmbeddedServletContainerCustomizerBeanPostProcessor 

    spring创建对象,填充属性之前,执行applyBeanPostProcessorsBeforeInitialization

     1 @Override
     2     public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
     3             throws BeansException {
     4 
     5         Object result = existingBean;
     6         for (BeanPostProcessor processor : getBeanPostProcessors()) {
     7             result = processor.postProcessBeforeInitialization(result, beanName);
     8             if (result == null) {
     9                 return result;
    10             }
    11         }
    12         return result;
    13     }
     1 public class EmbeddedServletContainerCustomizerBeanPostProcessor
     2         implements BeanPostProcessor, BeanFactoryAware {
     3 
     4     private ListableBeanFactory beanFactory;
     5 
     6     private List<EmbeddedServletContainerCustomizer> customizers;
     7 
     8 
     9     @Override
    10     public Object postProcessBeforeInitialization(Object bean, String beanName)
    11             throws BeansException {
    12         if (bean instanceof ConfigurableEmbeddedServletContainer) {//如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件
    13             postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
    14         }
    15         return bean;
    16     }
    17 
    18 private void postProcessBeforeInitialization(
    19             ConfigurableEmbeddedServletContainer bean) {
    20         for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {//获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
    21             customizer.customize(bean);
    22         }
    23     }
    24 
    25     private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
    26         if (this.customizers == null) {
    27             // Look up does not include the parent context
    28             this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(//从容器中获取所有这葛类型的组件:EmbeddedServletContainerCustomizer
    29                     this.beanFactory
    30                             .getBeansOfType(EmbeddedServletContainerCustomizer.class,
    31                                     false, false)
    32                             .values());
    33             Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
    34             this.customizers = Collections.unmodifiableList(this.customizers);
    35         }
    36         return this.customizers;
    37     }
    ServerProperties
     1 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
     2 public class ServerProperties
     3         implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
     4 
     5 @Override
     6     public void customize(ConfigurableEmbeddedServletContainer container) {
     7         if (getPort() != null) {
     8             container.setPort(getPort());
     9         }
    10         if (getAddress() != null) {
    11             container.setAddress(getAddress());
    12         }
    13         if (getContextPath() != null) {
    14             container.setContextPath(getContextPath());
    15         }
    16         if (getDisplayName() != null) {
    17             container.setDisplayName(getDisplayName());
          ......

    2)注册Servlet三大组件【Servlet、Filter、Listener】

      ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean

    1   @Bean
    2     public ServletRegistrationBean myServlet(){
    3         return new ServletRegistrationBean(new MyServlet(),"/myServlet");
    4     }

    3)嵌入式Servlet容器自动配置原理--EmbeddedServletContainerAutoConfiguration

     1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
     2 @Configuration
     3 @ConditionalOnWebApplication
     4 @Import(BeanPostProcessorsRegistrar.class)
     5 public class EmbeddedServletContainerAutoConfiguration {
     6 
     7     /**
     8      * Nested configuration if Tomcat is being used.
     9      */
    10     @Configuration
    11     @ConditionalOnClass({ Servlet.class, Tomcat.class })
    12     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    13     public static class EmbeddedTomcat {
    14 
    15         @Bean
    16         public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    17             return new TomcatEmbeddedServletContainerFactory();
    18         }
    19 
    20     }
    21 
    22     /**
    23      * Nested configuration if Jetty is being used.
    24      */
    25     @Configuration
    26     @ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
    27             WebAppContext.class })
    28     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    29     public static class EmbeddedJetty {
    30 
    31         @Bean
    32         public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
    33             return new JettyEmbeddedServletContainerFactory();
    34         }
    35 
    36     }
    37 
    38     /**
    39      * Nested configuration if Undertow is being used.
    40      */
    41     @Configuration
    42     @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
    43     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    44     public static class EmbeddedUndertow {
    45 
    46         @Bean
    47         public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
    48             return new UndertowEmbeddedServletContainerFactory();
    49         }
    50 
    51     }

     EmbeddedServletContainerFactory(嵌入式Servlet容器工厂)

     EmbeddedServletContainer:(嵌入式的Servlet容器)

    以TomcatEmbeddedServletContainerFactory为例

     1 public EmbeddedServletContainer getEmbeddedServletContainer(
     2             ServletContextInitializer... initializers) {
     3         Tomcat tomcat = new Tomcat();
     4         File baseDir = (this.baseDirectory != null) ? this.baseDirectory
     5                 : createTempDir("tomcat");
     6         tomcat.setBaseDir(baseDir.getAbsolutePath());
     7         Connector connector = new Connector(this.protocol);
     8         tomcat.getService().addConnector(connector);
     9         customizeConnector(connector);
    10         tomcat.setConnector(connector);
    11         tomcat.getHost().setAutoDeploy(false);
    12         configureEngine(tomcat.getEngine());
    13         for (Connector additionalConnector : this.additionalTomcatConnectors) {
    14             tomcat.getService().addConnector(additionalConnector);
    15         }
    16         prepareContext(tomcat.getHost(), initializers);
    17         return getTomcatEmbeddedServletContainer(tomcat);//将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;并且启动Tomcat服务器
    18     }

    4)嵌入式Servlet容器启动原理

      1、SpringBoot应用启动运行run方法

      2、refreshContext(context);SpringBoot刷新IOC容器【创建IOC容器对象,并初始化容器,创建容器中的每一
    个组件】;如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,否则:
    AnnotationConfigApplicationContext
      3、refresh(context);刷新刚才创建好的ioc容器;

     1 @Override
     2     public void refresh() throws BeansException, IllegalStateException {
     3         synchronized (this.startupShutdownMonitor) {
     4             // Prepare this context for refreshing.
     5             prepareRefresh();
     6 
     7             // Tell the subclass to refresh the internal bean factory.
     8             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
     9 
    10             // Prepare the bean factory for use in this context.
    11             prepareBeanFactory(beanFactory);
    12 
    13             try {
    14                 // Allows post-processing of the bean factory in context subclasses.
    15                 postProcessBeanFactory(beanFactory);
    16 
    17                 // Invoke factory processors registered as beans in the context.
    18                 invokeBeanFactoryPostProcessors(beanFactory);
    19 
    20                 // Register bean processors that intercept bean creation.
    21                 registerBeanPostProcessors(beanFactory);
    22 
    23                 // Initialize message source for this context.
    24                 initMessageSource();
    25 
    26                 // Initialize event multicaster for this context.
    27                 initApplicationEventMulticaster();
    28 
    29                 // Initialize other special beans in specific context subclasses.
    30                 onRefresh();
    31 
    32                 // Check for listener beans and register them.
    33                 registerListeners();
    34 
    35                 // Instantiate all remaining (non-lazy-init) singletons.
    36                 finishBeanFactoryInitialization(beanFactory);
    37 
    38                 // Last step: publish corresponding event.
    39                 finishRefresh();
    40             }
    41 
    42             catch (BeansException ex) {
    43                 if (logger.isWarnEnabled()) {
    44                     logger.warn("Exception encountered during context initialization - " +
    45                             "cancelling refresh attempt: " + ex);
    46                 }
    47 
    48                 // Destroy already created singletons to avoid dangling resources.
    49                 destroyBeans();
    50 
    51                 // Reset 'active' flag.
    52                 cancelRefresh(ex);
    53 
    54                 // Propagate exception to caller.
    55                 throw ex;
    56             }
    57 
    58             finally {
    59                 // Reset common introspection caches in Spring's core, since we
    60                 // might not ever need metadata for singleton beans anymore...
    61                 resetCommonCaches();
    62             }
    63         }
    64     }

      4、AnnotationConfigEmbeddedWebApplicationContext重写该onRefresh()。

    protected void onRefresh() {
            super.onRefresh();
            try {
                createEmbeddedServletContainer();
            }
            catch (Throwable ex) {
                throw new ApplicationContextException("Unable to start embedded container",
                        ex);
            }
        }
    
    private void createEmbeddedServletContainer() {
            EmbeddedServletContainer localContainer = this.embeddedServletContainer;
            ServletContext localServletContext = getServletContext();
            if (localContainer == null && localServletContext == null) {
                EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
                this.embeddedServletContainer = containerFactory
                        .getEmbeddedServletContainer(getSelfInitializer());
            }
            else if (localServletContext != null) {
                try {
                    getSelfInitializer().onStartup(localServletContext);
                }
                catch (ServletException ex) {
                    throw new ApplicationContextException("Cannot initialize servlet context",
                            ex);
                }
            }
            initPropertySources();
        }
  • 相关阅读:
    mysql_example
    windows 下 解决 go get 或 dep init 更新不了问题
    golang反射
    Windows下修改hosts并且让他立即生效
    Windows不重启就使环境变量修改生效
    swoole进程-2
    swoole进程
    swoole协程
    区间素数筛法
    AOJ
  • 原文地址:https://www.cnblogs.com/xiaoliangup/p/10393003.html
Copyright © 2011-2022 走看看