我的编程空间,编程开发者的网络收藏夹
学习永远不晚

springboot中如何利用Tomcat容器实现自启动

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

springboot中如何利用Tomcat容器实现自启动

这篇“springboot中如何利用Tomcat容器实现自启动”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springboot中如何利用Tomcat容器实现自启动”文章吧。

一、Spring通过注解导入Bean大体可分为四种方式,我们主要来说以下Import的两种实现方法:

1、通过实现ImportSerlector接口,实现Bean加载:

public class TestServiceImpl { public void testImpl() { System.out.println("我是通过importSelector导入进来的service"); }}public class TestService implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.ycdhz.service.TestServiceImpl"}; }}@Configuration@Import(value = {TestService.class})public class TestConfig {}public class TestController { @Autowired private TestServiceImpl testServiceImpl;  @RequestMapping("testImpl") public String testTuling() { testServiceImpl.testImpl(); return "Ok"; }}

2、 通过实现ImportSerlector接口,实现Bean加载:

public class TestService { public TestService() { System.out.println("我是通过ImportBeanDefinitionRegistrar导入进来的组件"); }}public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //定义一个BeanDefinition RootBeanDefinition beanDefinition = new RootBeanDefinition(TestService.class); //把自定义的bean定义导入到容器中 registry.registerBeanDefinition("testService",beanDefinition); }}@Configuration@Import(TestImportBeanDefinitionRegistrar.class)public class TestConfig {}

二、 Springboot启动过程中会自动装配

我们从spring-boot-autoconfigure-2.0.6.RELEASE.jar下搜索到Tomcat的相关配置,发现有两个自动装配类,分别包含了三个定制器(面向对象的单一职责原则),还有一个工厂类。

springboot中如何利用Tomcat容器实现自启动

2.1、TomcatWebServerFactoryCustomizer:定制Servlet和Reactive服务器通用的Tomcat特定功能。

public class TomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered { @Override public void customize(ConfigurableTomcatWebServerFactory factory) { ServerProperties properties = this.serverProperties; ServerProperties.Tomcat tomcatProperties = properties.getTomcat(); PropertyMapper propertyMapper = PropertyMapper.get(); propertyMapper.from(tomcatProperties::getBasedir).whenNonNull() .to(factory::setBaseDirectory); propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull() .as(Duration::getSeconds).as(Long::intValue) .to(factory::setBackgroundProcessorDelay); customizeRemoteIpValve(factory); propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive) .to((maxThreads) -> customizeMaxThreads(factory,  tomcatProperties.getMaxThreads())); propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive) .to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads)); propertyMapper.from(() -> determineMaxHttpHeaderSize()).when(this::isPositive) .to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,  maxHttpHeaderSize)); propertyMapper.from(tomcatProperties::getMaxHttpPostSize) .when((maxHttpPostSize) -> maxHttpPostSize != 0) .to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory,  maxHttpPostSize)); propertyMapper.from(tomcatProperties::getAccesslog) .when(ServerProperties.Tomcat.Accesslog::isEnabled) .to((enabled) -> customizeAccessLog(factory)); propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull() .to(factory::setUriEncoding); propertyMapper.from(properties::getConnectionTimeout).whenNonNull() .to((connectionTimeout) -> customizeConnectionTimeout(factory,  connectionTimeout)); propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive) .to((maxConnections) -> customizeMaxConnections(factory, maxConnections)); propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive) .to((acceptCount) -> customizeAcceptCount(factory, acceptCount)); customizeStaticResources(factory); customizeErrorReportValve(properties.getError(), factory); }}

2.2、ServletWebServerFactoryCustomizer:WebServerFactoryCustomizer 将ServerProperties属性应用于Tomcat web服务器。

public class ServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered { private final ServerProperties serverProperties; public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public int getOrder() { return 0; } @Override public void customize(ConfigurableServletWebServerFactory factory) { PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(this.serverProperties::getPort).to(factory::setPort); map.from(this.serverProperties::getAddress).to(factory::setAddress); map.from(this.serverProperties.getServlet()::getContextPath) .to(factory::setContextPath); map.from(this.serverProperties.getServlet()::getApplicationDisplayName) .to(factory::setDisplayName); map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession); map.from(this.serverProperties::getSsl).to(factory::setSsl); map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp); map.from(this.serverProperties::getCompression).to(factory::setCompression); map.from(this.serverProperties::getHttp2).to(factory::setHttp2); map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader); map.from(this.serverProperties.getServlet()::getContextParameters) .to(factory::setInitParameters); }}

2.3、ServletWebServerFactoryCustomizer :WebServerFactoryCustomizer 将ServerProperties属性应用于Tomcat web服务器。

public class TomcatServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>, Ordered { private final ServerProperties serverProperties; public TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public void customize(TomcatServletWebServerFactory factory) { ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat(); if (!ObjectUtils.isEmpty(tomcatProperties.getAdditionalTldSkipPatterns())) { factory.getTldSkipPatterns()  .addAll(tomcatProperties.getAdditionalTldSkipPatterns()); } if (tomcatProperties.getRedirectContextRoot() != null) { customizeRedirectContextRoot(factory,  tomcatProperties.getRedirectContextRoot()); } if (tomcatProperties.getUseRelativeRedirects() != null) { customizeUseRelativeRedirects(factory,  tomcatProperties.getUseRelativeRedirects()); } }}

三、有了TomcatServletWebServerFactory,相当于有了Spring加载的入口

通过AbstractApplicationContext#onReFresh()在IOC 容器中的带动tomcat启动,然后在接着执行 ioc容器的其他步骤。

我们通过断点可以观察Tomcat加载的整个生命周期,以及三个定制器的加载过程。

springboot中如何利用Tomcat容器实现自启动

@Overridepublic WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new 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引擎 configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } //刷新上下文 prepareContext(tomcat.getHost(), initializers); //准备启动 return getTomcatWebServer(tomcat);}
private void initialize() throws WebServerException { TomcatWebServer.logger .info("Tomcat initialized with port(s): " + getPortsDescription(false)); synchronized (this.monitor) { try { addInstanceIdToEngineName(); Context context = findContext(); context.addLifecycleListener((event) -> { if (context.equals(event.getSource())  && Lifecycle.START_EVENT.equals(event.getType())) {  // Remove service connectors so that protocol binding doesn't  // happen when the service is started.  removeServiceConnectors(); } }); // Start the server to trigger initialization listeners this.tomcat.start(); // We can re-throw failure exception directly in the main thread rethrowDeferredStartupExceptions(); try { ContextBindings.bindClassLoader(context, context.getNamingToken(),  getClass().getClassLoader()); } catch (NamingException ex) { // Naming is not enabled. Continue } // Unlike Jetty, all Tomcat threads are daemon threads. We create a // blocking non-daemon to stop immediate shutdown startDaemonAwaitThread(); } catch (Exception ex) { stopSilently(); throw new WebServerException("Unable to start embedded Tomcat", ex); } }}

备注: 在这个过程中我们需要了解Bean的生命周期,Tomcat的三个定制器均在BeanPostProcessorsRegistrar(Bean后置处理器)过程中加载;

  构造方法-->Bean后置处理器Before-->InitializingBean-->init-method-->Bean后置处理器After

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //构造方法 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Initialize the bean instance. ...... return exposedObject;}protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //Bean后置处理器Before wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //Bean后置处理器After wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean;}

以上就是关于“springboot中如何利用Tomcat容器实现自启动”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

springboot中如何利用Tomcat容器实现自启动

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

springboot中如何利用Tomcat容器实现自启动

这篇“springboot中如何利用Tomcat容器实现自启动”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springbo
2023-06-08

Tomcat中SpringBoot应用无法启动如何解决

Tomcat中SpringBoot应用无法启动如何解决?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。问题描述我修改pom.xml将打包方式改成warw
2023-05-31

kubernetes中如何实现Pod自动扩容与缩容

小编给大家分享一下kubernetes中如何实现Pod自动扩容与缩容,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一:简介Kubernetes通过HPA控制器,用于实现基本CPU使用率进行自动Pod扩容和缩容的功能。HAP
2023-06-04

如何在 Docker 容器中自动重启 golang 应用程序?

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《如何在 Docker 容器中自动重启 golang 应用程序?》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识
如何在 Docker 容器中自动重启 golang 应用程序?
2024-04-04

springboot中怎么利用logback启动报警报错如何解决

本篇文章为大家展示了springboot中怎么利用logback启动报警报错如何解决,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。springboot logback启动报警报错报错信息如下:16:
2023-06-20

如何使用shell实现自动重启服务

小编给大家分享一下如何使用shell实现自动重启服务,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!代码如下:#!/bin/bash if [ ! -f /tmp/
2023-06-09

利用Docker实现Nginx的自动扩展与缩容(如何通过Docker自动调整Nginx的扩展与缩容?)

Docker和Kubernetes提供了通过Prometheus和Grafana监控指标,以及使用水平Pod自动扩缩器(HPA)实现Nginx自动扩展和缩容的方法。该解决方案包括使用DockerCompose定义配置,使用Prometheus收集Nginx指标,使用Grafana创建警报,使用KubernetesDeployment定义副本数,并使用HPA根据指标触发自动扩展或缩容。这有助于优化资源利用,确保应用程序在负载变化时自动调整其容量。最佳实践包括设置适当的阈值、监控指标,以及使用自动部署流程。
利用Docker实现Nginx的自动扩展与缩容(如何通过Docker自动调整Nginx的扩展与缩容?)
2024-04-02

利用JSP 如何实现获取spring容器中的bean

这篇文章给大家介绍利用JSP 如何实现获取spring容器中的bean,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JSP 获取spring容器中bean的方法总结方案1(Web中使用):ApplicationCont
2023-05-31

如何利用Python实现自动扫雷小脚本

小编给大家分享一下如何利用Python实现自动扫雷小脚本,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、准备工作1.扫雷游戏我是win10,没有默认的扫雷,所以
2023-06-15

详解如何利用Python实现报表自动化

这篇文章主要介绍了报表自动化的流程,并教你用Python实现工作中的一个报表自动化实战,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
2023-05-14

如何利用Gitlab和Kubernetes实现自动化部署

GitlabK8s自动化部署随着云计算和容器化技术的普及,企业越来越多地将应用程序部署在 Kubernetes 上。而为了更好地管理 Kubernetes 环境中的应用程序,越来越多的企业选择使用 Gitlab 和 Kubernetes 的
2023-10-22

如何实现服务器应用自动重新启动IIS批处理

这篇文章主要讲解了“如何实现服务器应用自动重新启动IIS批处理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现服务器应用自动重新启动IIS批处理”吧!设想:写一个批处理,每小时重新启动
2023-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录