当前位置:

首页 > 编程开发 > springboot中如何利用Tomcat容器实现自启动

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

一、Spring通过注解导入Bean大体可分为四种方式,我们主要来说以下Import的两种实现方法:1、通过实现ImportSerlector接口,实现Bean加载:publicclassTestServiceImpl{publicvoidtestImpl(){System.out.println("我是通过importSelector导入进来的service");}}publicclassTestServiceimplementsImportSelector{@OverridepublicString[

本文目录

    一、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, 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, 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, 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容器实现自启动

    @Override
    public 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) () -> {
     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;
    }                        
                                                    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
                                                    
    作者最新文章
    编程开发 tomcat
    相关文章 更多
    tomcat启动失败的原因和解决办法详解
    tomcat启动失败的原因和解决办法详解

    详细分析 Tomcat 启动失败的常见原因,并提供可操作的排查和解决方案。

    修改tomcat的默认端口号配置文件及操作步骤
    修改tomcat的默认端口号配置文件及操作步骤

    详细讲解如何在Tomcat中通过编辑conf/server.xml文件来修改默认的HTTP连接器端口,包含文件路径查找、关键标签定位及重启服务的完整步骤。

    tomcat部署项目流程详细步骤与配置教程
    tomcat部署项目流程详细步骤与配置教程

    手把手教你如何在Tomcat中部署Web项目,包括自动部署与手动配置server.xml的方法,解决端口冲突和路径访问问题,适合Java初学者和运维人员参考。

    tomcat安装与环境变量配置教程及完整操作步骤
    tomcat安装与环境变量配置教程及完整操作步骤

    手把手教你在Windows系统中安装Apache Tomcat并配置关键环境变量。涵盖JDK验证、CATALINA_HOME设置及启动测试,确保Web服务器正常运行,适合Java初学者参考。

    flex tomcat端口被占用的问题分析及解决方法
    flex tomcat端口被占用的问题分析及解决方法

    启动Tomcat时若8080端口被占用,可在命令行输入`netstat-ano`查找PID,再于任务管理器结束该进程,最后重新启动Tomcat即可释放端口并正常运行。

    solaris 10下安装java+tomcat
    solaris 10下安装java+tomcat

    在Solaris系统上配置Ja va和Tomcat环境,说起来不算复杂,但一些细节如果不注意,很容易卡壳。下面以Solaris10为例,把整个流程拆开讲清楚,跟着步骤走就能搞定。 1. Ja va安装 先把安装文件 j2re-1_4_2_05-solaris-i586.sh 上传到 /export/

    Windows下Tomcat8注册为服务及开机自启设置
    Windows下Tomcat8注册为服务及开机自启设置

    在Windows10专业版1909上安装并配置Tomcat8.5.34以注册为服务并设置开机自启的实践笔记。以下是我对Tomcat进行的调整:0.1.注册为Windows服务0.2.更改开机启动方式0.3.POST提交长度修改0.4.改访问端口0.5.增加静态资源的缓存0.6.改内存0.7.加编码UTF-8默认设置:默认服务名:Tomcat8默认服务显示名称:ApacheTomcat8.5Tomcat8默认启动方式:手动启动默认内存:128m至256m下载官

    Web后端开发入门指南(2)
    Web后端开发入门指南(2)

    大家好,很高兴再次与你们见面,我是你们的朋友全栈君。设置JavaWeb应用开发环境——Tomcat服务器的下载与安装首先,搜索Tomcat,找到如下网址:点击链接,进入Tomcat官方网站。在左侧栏找到“Download”选项,选择最新版的Tomcat9,点击进入。向下滚动,找到如图所示的位置,Core核心部分提供zip版、tar.gz版(适用于Linux系统)、32位版、64位版以及安装版。如果不需要安装程序,请选择前几个版本;如果需要安装程序,则下载最后一个版本。选择适合自己的版本进行下载。安

    详细指引:Tomcat的部署和性能优化
    详细指引:Tomcat的部署和性能优化

    Tomcat是一个常用的JavaWeb应用服务器,用于部署和运行JavaWeb应用程序。下面是Tomcat部署和优化的详细教程:部署Tomcat:下载Tomcat:访问ApacheTomcat官方网站()下载适合你的操作系统的Tomcat版本。解压Tomcat:将下载的Tomcat压缩包解压到目标目录,例如/opt/tomcat。配置环境变量:将Tomcat的bin目录路径添加到系统的PATH环境变量中,以便在任何位置都可以使用Tomcat命令。启动Tomcat:打开终端,进入Tomcat的bin目录,执

    springBoot项目常用目录有哪些
    springBoot项目常用目录有哪些

    springBoot项目常用目录springBoot项目的目录结构及名规范介绍基于SpringBoot开发时的目录结构及命名规范,通过介绍能够为你解决,在实际项目中如何规划目录结构?如何命名目录更规范?各个目录分别代表什么含义?等三个问题。目录说明servicex//项目名|-admin-ui//管理服务前端代码(一般将UI和SERVICE放到一个工程中,便于管理)|-servicex-auth//模块1|-servicex-common//模块2|-servicex-gateway//模块3|-serv

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    为什么要购买正版软件?
    01 官方授权

    授权来源透明,订单与许可信息可随时查询。

    02 即时交付

    付款成功后自动发放激活信息,支持订单追踪。

    03 中文协助

    安装、激活、迁移与续费问题都有专人响应。

    04 长期可用

    提供升级提醒与授权管理,换机时也能轻松迁移。

    网站备案号:苏ICP备2026018738号-1 联系邮箱:bd@zhengruan.com 网站地图

    Copyright ©2018-2026