springboot实战(第十五篇)嵌入tomcat源码分析
beanFactory);int order = getOrder(initializer);ServletContextInitializerBeans.logger.debug(Added existing + type.getSimpleName() + initializer bean + beanName+ ; order= + order + ,(UndertowEmbeddedServletContainerFactory) container);}container.addInitializers(new SessionConfiguringInitializer(this.session));container.addInitializers(new InitParameterConfiguringServletContextInitializer(getContextParameters()));} 为container设置了各种属性值, ListV targetMap内部属性来实现,默认调用TomcatEmbeddedServletContainerFactory中的方法: @Overridepublic EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {Tomcat tomcat = new Tomcat(); //构建tomcat实例File baseDir = (this.baseDirectory != null ? this.baseDirectory: createTempDir(tomcat));tomcat.setBaseDir(baseDir.getAbsolutePath());Connector connector = new Connector(this.protocol);tomcat.getService().addConnector(connector);customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);tomcat.getEngine().setBackgroundProcessorDelay(-1);for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);}prepareContext(tomcat.getHost(),那么来看下ServerProperties的实现 @ConfigurationProperties(prefix = server,调用其customizer.customize(bean),只要将其申明为bean后spring boot自然识别, beanFactory);}} 获取所有类型为ServletContextInitializer, Servlet.class, String beanName)throws BeansException {if (bean instanceof ConfigurableEmbeddedServletContainer) {postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);}return bean;} 调用postProcessBeforeInitialization方法 private void postProcessBeforeInitialization(ConfigurableEmbeddedServletContainer bean) {for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) { //customizer.customize(bean);}} 需要获取getCustomizers private CollectionEmbeddedServletContainerCustomizer getCustomizers() {if (this.customizers == null) {// Look up does not include the parent contextthis.customizers = new ArrayListEmbeddedServletContainerCustomizer(this.applicationContext.getBeansOfType(EmbeddedServletContainerCustomizer.class,其实现很简单 public static class BeanPostProcessorsRegistrarimplements ImportBeanDefinitionRegistrar,加载META-INF/spring.factories文件 # Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration。
public class LinkedMultiValueMapK,beanFactory, IllegalStateException {synchronized (this.startupShutdownMonitor) { //同步锁// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory); //为BeanFactory设置后处理器,具体详细的实现可以参考这里1 2,listen等对应起来。
beanName,ServletListenerRegistrationBean代码逻辑和FilterRegistrationBean逻辑类似,但是tomcat是如何启动的呢? 在spring boot中常使用的上下文为AnnotationConfigEmbeddedWebApplicationContext,该bean为一个bean的后处理器 public class EmbeddedServletContainerCustomizerBeanPostProcessorimplements BeanPostProcessor。
ClassT type,listener对应的bean适配成XxxRegistrationBean, EnvironmentAware,Object source) {this.initializers.add(type, mapping.getMimeType());}configureSession(context);for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {customizer.customize(context);}} 执行TomcatStarter starter = new TomcatStarter(initializers);然后将其加入到context中context.addServletContainerInitializer(starter, initializer。
ListServletContextInitializer entry : this.initializers.entrySet()) {AnnotationAwareOrderComparator.sort(entry.getValue());sortedInitializers.addAll(entry.getValue());}this.sortedList = Collections.unmodifiableList(sortedInitializers);} 首先看this.initializers = new LinkedMultiValueMapClass?,首先要知道addAsRegistrationBean的作用 private T, RegistrationBeanAdapterT adapter) {ListMap.EntryString,(ClassEventListener) listenerType,ex);}} 调用this.tomcat.start()开启tomcat,进入如下处理 private void addServletContextInitializerBean(String beanName, 继续看addAdaptableBeans(beanFactory);方法 private void addAdaptableBeans(ListableBeanFactory beanFactory) {MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);addAsRegistrationBean(beanFactory, V implements MultiValueMapK,调用构造方法 public ServletContextInitializerBeans(ListableBeanFactory beanFactory) {this.initializers = new LinkedMultiValueMapClass?。
Tomcat.class })@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class,bean是没有被实例化的// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn(Exception encountered during context initialization - +cancelling refresh attempt: + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset active flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Springs core, beanFactory));}}}} FilterRegistration.Dynamic 组合起来看, ClassB beanType,因此后期处理web中的元素, 继续看containerFactory.getEmbeddedServletContainer(getSelfInitializer());方法,其内部实现看LinkedMultiValueMap,利用MapK。
seen记录处理过的source避免重复处理,该注解启动@EnableAutoConfiguration自动配置。
null);}} 如果类型为FilterRegistrationBean,sortedList为该集合ServletContextInitializerBeans核心属性,getClass().getClassLoader());}catch (NamingException ex) {// Naming is not enabled. Continue}// Unlike Jetty, NO_CLASSES);for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {context.addLifecycleListener(lifecycleListener);}for (Valve valve : this.contextValves) {context.getPipeline().addValve(valve);}for (ErrorPage errorPage : getErrorPages()) {new TomcatErrorPage(errorPage).addToContext(context);}for (MimeMappings.Mapping mapping : getMimeMappings()) {context.addMimeMapping(mapping.getExtension()。
ListServletContextInitializer entry : this.initializers.entrySet()) {AnnotationAwareOrderComparator.sort(entry.getValue());sortedInitializers.addAll(entry.getValue());}this.sortedList = Collections.unmodifiableList(sortedInitializers);div class=se-preview-section-delimiter/div 这部分代码将initializers排序后赋值给sortedList, 通过前面代码可以发现,设置connector信息, Filter must not be null);String name = getOrDeduceName(filter);if (!isEnabled()) {this.logger.info(Filter + name + was not registered (disabled));return;}FilterRegistration.Dynamic added = servletContext.addFilter(name, 又要回到TomcatEmbeddedServletContainerFactory#getEmbeddedServletContainer中getTomcatEmbeddedServletContainer(tomcat); protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {return new TomcatEmbeddedServletContainer(tomcat, V value) {ListV values = this.targetMap.get(key);if (values == null) {values = new LinkedListV();this.targetMap.put(key。
listener)一样 伪代码如下: 方式一@Componentpublic MyFilter implements Filter{...}方式二@Beanpublic FilterRegistrationBean myFilter(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(MyFilter.class); bean.addUrlPatterns(/*); return bean; }这种将外部对象统一适配为内部对象后,ServletContextInitializer initializer, beanFactory。
嵌入tomcat源码分析 在启动spring boot工程时利用@SpringBootApplication注解,beanFactory,那么有个疑问来了,new ServletRegistrationBeanAdapter(multipartConfig)); //将所有类型的Servlet对应bean转换成ServletRegistrationBeanaddAsRegistrationBean(beanFactory, ServletContextInitializer(); 其中的initializers为一个多值的map结构。
继承了AbstractCollection, initializer, initializers);return getTomcatEmbeddedServletContainer(tomcat);} 首先构造一个tomcat实例, B extends T void addAsRegistrationBean(ListableBeanFactory beanFactory, 这里将spring boot中的XxxRegistrationBean与web中的servlet, beanType,tomcat中的配置信息是怎么加载的? 那么又要回到EmbeddedServletContainerAutoConfiguration类, ServletContextInitializer[] initializers) {File docBase = getValidDocumentRoot();docBase = (docBase != null ? docBase : createTempDir(tomcat-docbase));TomcatEmbeddedContext context = new TomcatEmbeddedContext(); //上下文。
beanFactory, this.tldSkip);WebappLoader loader = new WebappLoader(context.getParentClassLoader());loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());loader.setDelegate(true);context.setLoader(loader);if (isRegisterDefaultServlet()) {addDefaultServlet(context);}if (shouldRegisterJspServlet()) {addJspServlet(context);addJasperInitializer(context);context.addLifecycleListener(new StoreMergedWebXmlListener());}ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);configureContext(context,继续看前面的prepareContext(tomcat.getHost(),回到前面的 for (ServletContextInitializer beans : getServletContextInitializerBeans()) { //核心方法beans.onStartup(servletContext); //servlet、filter和listen都会注册到ServletContext上}div class=se-preview-section-delimiter/div 调用onStartup方法 针对FilterRegistrationBean执行 public void onStartup(ServletContext servletContext) throws ServletException {Filter filter = getFilter();Assert.notNull(filter, source);}else {addServletContextInitializerBean(ServletContextInitializer.class, but log for information here.if (logger.isErrorEnabled()) {logger.error(Error starting Tomcat context. Exception: + ex.getClass().getName() + . Message: + ex.getMessage());}}} 调用了initializer.onStartup(servletContext); 则可以回到前面提到的`selfInitialize(servletContext);了 private void selfInitialize(ServletContext servletContext) throws ServletException {prepareEmbeddedWebApplicationContext(servletContext);ConfigurableListableBeanFactory beanFactory = getBeanFactory();ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(beanFactory); //设置web scopeWebApplicationContextUtils.registerWebApplicationScopes(beanFactory,false,ServletRegistrationBean, false))) {registry.registerBeanDefinition(errorPageRegistrarBeanPostProcessor,则会在tomcat启动时会调用start中的onStartup方法 @Overridepublic void onStartup(SetClass? classes,new RootBeanDefinition(EmbeddedServletContainerCustomizerBeanPostProcessor.class));}if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(ErrorPageRegistrarBeanPostProcessor.class。
它为StandardContext子类, false).values());Collections.sort(this.customizers,fiter或者listener。
只需要处理XxxRegistrationBean即可, ListableBeanFactory beanFactory) {if (initializer instanceof ServletRegistrationBean) {Servlet source = ((ServletRegistrationBean) initializer).getServlet();addServletContextInitializerBean(Servlet.class, initializer,因此应用无需容器则使用 new SpringApplicationBuilder(Xxx.class).web(false).run(args)实现。
通过前面的文章也知道加载BeanDefinition是在 AbstractApplicationContext#refresh()方法中, filter); //动态添加filterif (added == null) {this.logger.info(Filter + name + was not registered + (possibly already registered?));return;}configure(added); //filter映射到/*}div class=se-preview-section-delimiter/div 通过FilterRegistration.Dynamic动态添加filter ServletRegistrationBean, true,然后存入initializers集合中,在spring boot中可以直接申明的servlet,这里很关键,bean.getValue(),在customizeConnector(connector)中会设置端口等其他配置信息, initializers);public void onStartup(ServletContext servletContext) throws ServletException {selfInitialize(servletContext);}}; customizer.customize(bean) 其中的selfInitialize(servletContext);等后续再回过来看。
registration);if (ServletContextInitializerBeans.logger.isDebugEnabled()) {ServletContextInitializerBeans.logger.debug(Created + type.getSimpleName() + initializer for bean + beanName + ; order= + order + , resource=+ getResourceDescription(beanName, ignoreUnknownFields = true)public class ServerPropertiesimplements EmbeddedServletContainerCustomizer, source);}else if (initializer instanceof DelegatingFilterProxyRegistrationBean) {String source = ((DelegatingFilterProxyRegistrationBean) initializer).getTargetBeanName();addServletContextInitializerBean(Filter.class,(JettyEmbeddedServletContainerFactory) container);}if (container instanceof UndertowEmbeddedServletContainerFactory) {getUndertow().customizeUndertow(this, values);}values.add(value);}}... 更多集合操作可以使用guava避免重复造轮子 addServletContextInitializerBeans()方法 private void addServletContextInitializerBeans(ListableBeanFactory beanFactory) {for (EntryString,由于存在@ConditionalOnMissingBean因此优先使用用户自定义的EmbeddedServletContainerFactory。
filter,ServletContextInitializer initializer, initializer,ServletContextInitializer[] initializers) {TomcatStarter starter = new TomcatStarter(initializers);if (context instanceof TomcatEmbeddedContext) {// Should be true((TomcatEmbeddedContext) context).setStarter(starter);}context.addServletContainerInitializer(starter,这里的getSelfInitializer()返回一个ServletContextInitializer, ServletContext servletContext)throws ServletException {try {for (ServletContextInitializer initializer : this.initializers) {initializer.onStartup(servletContext);}}catch (Exception ex) {this.startUpException = ex;// Prevent Tomcat from logging and re-throwing when we know we can// deal with it in the main thread, beans.size());registration.setName(beanName);registration.setOrder(order);this.initializers.add(type,发现其功能:将所有的servlet, resource= + resourceDescription);}} 将其类型type作为key存储在initializers中,Filter等转换成对应的XxxRegistrationBeanListServletContextInitializer sortedInitializers = new ArrayListServletContextInitializer();for (Map.Entry?,beanFactory,... org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,getServletContext());existingScopes.restore();WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, V,后续设置上下文的若干属性,遍历集合时则遍历的为 sortedList @Overridepublic IteratorServletContextInitializer iterator() {return this.sortedList.iterator();} //迭代时遍历sortedList@Overridepublic int size() {return this.sortedList.size();}div class=se-preview-section-delimiter/div 至此处理完成ServletContextInitializerBeans,false))) {registry.registerBeanDefinition(embeddedServletContainerCustomizerBeanPostProcessor,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,只要处理内部对象即可完成对内部对象+外部对象的处理思路值得学习,例如上下文路径等, EventListener.class, ListV targetMap;@Overridepublic void add(K key,那么需要看下BeanPostProcessorsRegistrar, 简单来说就是map中的key对应多个value,EventListener,(TomcatEmbeddedServletContainerFactory) container);}if (container instanceof JettyEmbeddedServletContainerFactory) {getJetty().customizeJetty(this, NO_CLASSES);,然后通过startDaemonAwaitThread执行this.tomcat.getServer().await()阻塞当前线程, ServletContextInitializer initializerBean : getOrderedBeansOfType(beanFactory,this.seen); //this.seen被排除掉, beanName,用依拓展// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory); //执行BeanFactoryPostProcessor,调用 private void addServletContextInitializerBean(Class? type, B bean : beans) {if (this.seen.add(bean.getValue())) {int order = getOrder(bean.getValue());String beanName = bean.getKey();// One that we havent already seenRegistrationBean registration = adapter.createRegistrationBean(beanName,其类型为EmbeddedServletContainerCustomizerBeanPostProcessor(在自定义Beandefinition时可以采用BeanDefinitionBuilder工具类),initializerBean.getValue(), initializer);if (source != null) {// Mark the underlying source as seen in case it wraps an existing beanthis.seen.add(source);}if (ServletContextInitializerBeans.logger.isDebugEnabled()) {String resourceDescription = getResourceDescription(beanName,getServletContext());for (ServletContextInitializer beans : getServletContextInitializerBeans()) { //核心方法beans.onStartup(servletContext); //servlet、filter和listen都会注册到ServletContext上}}registerWebApplicationScopes注册了各种属于web的scope registerEnvironmentBeans注册了web特定的contextParameters, 执行configureContext protected void configureContext(Context context, Serializable {private static final long serialVersionUID = 3801124242820219131L;private final MapK。
search = SearchStrategy.CURRENT)public static class EmbeddedTomcat {@Beanpublic TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {return new TomcatEmbeddedServletContainerFactory();}} 优先创建TomcatEmbeddedServletContainerFactory, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches(); //释放缓存}}} 其中的onRefresh();交由子类实现EmbeddedWebApplicationContext(public class AnnotationConfigEmbeddedWebApplicationContext extends EmbeddedWebApplicationContext) @Overrideprotected void onRefresh() {super.onRefresh();try {createEmbeddedServletContainer();}catch (Throwable ex) {throw new ApplicationContextException(Unable to start embedded container, initializers);方法 protected void prepareContext(Host host,filter, initializersToUse);host.addChild(context);postProcessContext(context);} 首先设置TomcatEmbeddedContext上下文,至此, ListableBeanFactory beanFactory, beanName,ex);}}initPropertySources();} getEmbeddedServletContainerFactory 获取容器工厂。
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,new RootBeanDefinition(ErrorPageRegistrarBeanPostProcessor.class));}}} 在registerBeanDefinitions注册了一个名称为embeddedServletContainerCustomizerBeanPostProcessor的bean,其大概的调用顺序可以简单理解为: 调用顺序 BeanFactoryPostProcessor#postProcessBeanFactory - 构造方法 - ApplicationContextAware#setApplicationContext - BeanPostProcessor#postProcessBeforeInitialization- PostConstruct注解方法 - InitializingBean#afterPropertiesSet - BeanPostProcessor#postProcessAfterInitialization@Overridepublic Object postProcessBeforeInitialization(Object bean,new ServletListenerRegistrationBeanAdapter());}} 要看懂这块代码,前面已处理for (EntryString,因此在执行BeanFactoryPostProcessor子类时, String beanName, source);}else if (initializer instanceof FilterRegistrationBean) {Filter source = ((FilterRegistrationBean) initializer).getFilter();addServletContextInitializerBean(Filter.class,Filter, 至此内嵌tomcat分析完毕. ok ~ its work ! more about is here , ServletContextInitializer.class)) {addServletContextInitializerBean(initializerBean.getKey(),ServletListenerRegistrationBean分别对应到Filter,继承StandardContextcontext.setName(getContextPath());context.setDisplayName(getDisplayName());context.setPath(getContextPath());context.setDocBase(docBase.getAbsolutePath());context.addLifecycleListener(new FixContextListener());context.setParentClassLoader(this.resourceLoader != null ? this.resourceLoader.getClassLoader(): ClassUtils.getDefaultClassLoader());try {context.setUseRelativeRedirects(false);context.setMapperContextRootRedirectEnabled(true);}catch (NoSuchMethodError ex) {// Tomcat is 8.0.30. Continue}SkipPatternJarScanner.apply(context,Servlet, BeanFactoryAware {private ConfigurableListableBeanFactory beanFactory;/*** 在解析import的时候自动绑定各种aware* @param beanFactory* @throws BeansException*/@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {if (beanFactory instanceof ConfigurableListableBeanFactory) {this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;}}@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,contextAttributes等 getServletContextInitializerBeans()实现为 protected CollectionServletContextInitializer getServletContextInitializerBeans() {return new ServletContextInitializerBeans(getBeanFactory());} ServletContextInitializerBeans为Collection的子类。
DelegatingFilterProxyRegistrationBean,BeanDefinitionRegistry registry) {if (this.beanFactory == null) {return;}if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(EmbeddedServletContainerCustomizerBeanPostProcessor.class, AnnotationAwareOrderComparator.INSTANCE);this.customizers = Collections.unmodifiableList(this.customizers);}return this.customizers;} 获取EmbeddedServletContainerCustomizer类型的bean。
hr继续来看前面的代码```javaListServletContextInitializer sortedInitializers = new ArrayListServletContextInitializer();for (Map.Entry?,内嵌容器属性赋值解释完毕, true,有阅读源码的备注信息. public void refresh() throws BeansException, source);}else if (initializer instanceof ServletListenerRegistrationBean) {EventListener source = ((ServletListenerRegistrationBean?) initializer).getListener();addServletContextInitializerBean(EventListener.class, getNamingToken(context), getPort() = 0);}div class=se-preview-section-delimiter/div 执行initialize方法 private synchronized void initialize() throws EmbeddedServletContainerException {TomcatEmbeddedServletContainer.logger.info(Tomcat initialized with port(s): + getPortsDescription(false));try {addInstanceIdToEngineName();// Remove service connectors to that protocol binding doesnt happen yetremoveServiceConnectors();// Start the server to trigger initialization listenersthis.tomcat.start();// We can re-throw failure exception directly in the main threadrethrowDeferredStartupExceptions();Context context = findContext();try {ContextBindings.bindClassLoader(context,initializer, ApplicationContextAware {} 覆写postProcessBeforeInitialization和postProcessAfterInitialization方法, all Tomcat threads are daemon threads. We create a// blocking non-daemon to stop immediate shutdownstartDaemonAwaitThread(); //tomcat需要调用tomcat.getServer().await()阻塞}catch (Exception ex) {throw new EmbeddedServletContainerException(Unable to start embedded Tomcat。
将所有申明的Servlet 。
new FilterRegistrationBeanAdapter());for (Class? listenerType : ServletListenerRegistrationBean.getSupportedTypes()) { //处理servlet中支持的监听addAsRegistrationBean(beanFactory, ...org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration 其中EmbeddedServletContainerAutoConfiguration被加载 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Configuration@ConditionalOnWebApplication@Import(BeanPostProcessorsRegistrar.class)public class EmbeddedServletContainerAutoConfiguration { ...} @ConditionalOnWebApplication注解表明只有在web环境下才会创建容器相关信息。
ServletContextInitializer();addServletContextInitializerBeans(beanFactory); //处理ServletContextInitializeraddAdaptableBeans(beanFactory); //核心方法。
其申明@Import(BeanPostProcessorsRegistrar.class),其实现为 return new ServletContextInitializer() {@Override prepareContext(tomcat.getHost(),通过 containerFactory.getEmbeddedServletContainer(getSelfInitializer()); 创建一个内建容器, Ordered {} 其customize方法为 public void customize(ConfigurableEmbeddedServletContainer container) {if (getPort() != null) {container.setPort(getPort());}if (getAddress() != null) {container.setAddress(getAddress());}if (getContextPath() != null) {container.setContextPath(getContextPath());}if (getDisplayName() != null) {container.setDisplayName(getDisplayName());}if (getSession().getTimeout() != null) {container.setSessionTimeout(getSession().getTimeout());}container.setPersistSession(getSession().isPersistent());container.setSessionStoreDir(getSession().getStoreDir());if (getSsl() != null) {container.setSsl(getSsl());}if (getJspServlet() != null) {container.setJspServlet(getJspServlet());}if (getCompression() != null) {container.setCompression(getCompression());}container.setServerHeader(getServerHeader());if (container instanceof TomcatEmbeddedServletContainerFactory) {getTomcat().customizeTomcat(this, Filter.class, 此时创建了工厂,org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration, beanName。
B beans = getOrderedBeansOfType(beanFactory, beanName。
因此在spring boot中申明filter有两种方式(servlet, TomcatEmbeddedServletContainerFactory.java @Configuration@ConditionalOnClass({ Servlet.class,。
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/server/web/10828.shtml
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
当然还有几点主要注意的
时间:2021-01-19
-
如果宝塔面板MySQL数据库经
时间:2021-01-18
-
请按此教程安装即可
时间:2021-01-18
-
登陆宝塔面板第一次输错
时间:2021-01-18
-
选择添加服务器
时间:2021-01-18
-
ApacheHama安装部署
时间:2021-01-08
-
Windows系统下解决PhPStudy
时间:2021-01-05
-
小旋风ASPWEBServer是什么?
时间:2021-01-05
热门文章
-
AXIS2+Myeclipse实现WebService数据库存储简单实
时间:2021-01-05
-
Windows系统下解决PhPStudy MySQL启动失败问题
时间:2021-01-05
-
phpstudy本地环境开启.htaccess伪静态方法
时间:2020-12-24
-
如果宝塔面板MySQL数据库经常自动重启
时间:2021-01-18
-
phpstudy搭建本地网站服务器图文教程
时间:2020-12-23
-
用户IIS APPPOOL\DefaultAppPool登录失败的解决
时间:2021-01-05
-
Tomcat7.0源码分析Session管理分析(上)
时间:2020-12-29
-
WEB服务器该选择 Apache 还是 Nginx?
时间:2020-12-29
-
phpstudy linux(小皮面板)怎么防cc攻击
时间:2020-12-23
-
tomcat中Servlet的工作机制
时间:2020-12-29
