iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何在SpringBoot中启动tomcat
  • 687
分享到

如何在SpringBoot中启动tomcat

2023-06-14 22:06:06 687人浏览 泡泡鱼
摘要

如何在SpringBoot中启动Tomcat?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。springboot是什么springboot一种全新的编程规范,其设计目的是用来

如何在SpringBoot中启动Tomcat?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

springboot是什么

springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。

内置tomcat

开发阶段对我们来说使用内置的tomcat是非常够用了,当然也可以使用jetty。

<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-WEB</artifactId>   <version>2.1.6.RELEASE</version></dependency>
@SpringBootApplicationpublic class MySpringbootTomcatStarter{    public static void main(String[] args) {        Long time=System.currentTimeMillis();        SpringApplication.run(MySpringbootTomcatStarter.class);        System.out.println("===应用启动耗时:"+(System.currentTimeMillis()-time)+"===");    }}

这里是main函数入口,两句代码最耀眼,分别是SpringBootApplication注解和SpringApplication.run()方法。

发布生产

发布的时候,目前大多数的做法还是排除内置的tomcat,打瓦包(war)然后部署在生产的tomcat中,好吧,那打包的时候应该怎么处理?

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    <!-- 移除嵌入式tomcat插件 -->    <exclusions>        <exclusion>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-tomcat</artifactId>        </exclusion>    </exclusions></dependency><!--添加servlet-api依赖---><dependency>    <groupId>javax.servlet</groupId>    <artifactId>javax.servlet-api</artifactId>    <version>3.1.0</version>    <scope>provided</scope></dependency>

更新main函数,主要是继承SpringBootServletInitializer,并重写configure()方法。

@SpringBootApplicationpublic class MySpringbootTomcatStarter extends SpringBootServletInitializer {    public static void main(String[] args) {        Long time=System.currentTimeMillis();        SpringApplication.run(MySpringbootTomcatStarter.class);        System.out.println("===应用启动耗时:"+(System.currentTimeMillis()-time)+"===");    }    @Override    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {        return builder.sources(this.getClass());    }}

从main函数说起

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {    return run(new Class[]{primarySource}, args);}

--这里run方法返回的是ConfigurableApplicationContext

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return (new SpringApplication(primarySources)).run(args);}
public ConfigurableApplicationContext run(String... args) { ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try {  ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);  ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);  this.configureIgnoreBeanInfo(environment);    //打印banner,这里你可以自己涂鸦一下,换成自己项目的loGo  Banner printedBanner = this.printBanner(environment);    //创建应用上下文  context = this.createApplicationContext();  exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);  //预处理上下文  this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);    //刷新上下文  this.refreshContext(context);    //再刷新上下文  this.afterRefresh(context, applicationArguments);    listeners.started(context);  this.callRunners(context, applicationArguments); } catch (Throwable var10) {   } try {  listeners.running(context);  return context; } catch (Throwable var9) {   }}

既然我们想知道tomcat在SpringBoot中是怎么启动的,那么run方法中,重点关注创建应用上下文(createApplicationContext)和刷新上下文(refreshContext)。

创建上下文

//创建上下文protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) {  try {   switch(this.webApplicationType) {    case SERVLET:                    //创建AnnotationConfigServletWebServerApplicationContext        contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");     break;    case ReactIVE:     contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");     break;    default:     contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");   }  } catch (ClassNotFoundException var3) {   throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);  } } return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);}

这里会创建AnnotationConfigServletWebServerApplicationContext类。
而AnnotationConfigServletWebServerApplicationContext类继承了ServletWebServerApplicationContext,而这个类是最终集成了AbstractApplicationContext。

刷新上下文

//SpringApplication.java//刷新上下文private void refreshContext(ConfigurableApplicationContext context) { this.refresh(context); if (this.reGISterShutdownHook) {  try {   context.registerShutdownHook();  } catch (AccessControlException var3) {  } }}
//这里直接调用最终父类AbstractApplicationContext.refresh()方法protected void refresh(ApplicationContext applicationContext) { ((AbstractApplicationContext)applicationContext).refresh();}//AbstractApplicationContext.javapublic void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) {  this.prepareRefresh();  ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();  this.prepareBeanFactory(beanFactory);  try {   this.postProcessBeanFactory(beanFactory);   this.invokeBeanFactoryPostProcessors(beanFactory);   this.registerBeanPostProcessors(beanFactory);   this.initMessageSource();   this.initApplicationEventMulticaster();   //调用各个子类的onRefresh()方法,也就说这里要回到子类:ServletWebServerApplicationContext,调用该类的onRefresh()方法   this.onRefresh();   this.registerListeners();   this.finishBeanFactoryInitialization(beanFactory);   this.finishRefresh();  } catch (BeansException var9) {   this.destroyBeans();   this.cancelRefresh(var9);   throw var9;  } finally {   this.resetCommonCaches();  } }}
//ServletWebServerApplicationContext.java//在这个方法里看到了熟悉的面孔,this.createWebServer,神秘的面纱就要揭开了。protected void onRefresh() { super.onRefresh(); try {  this.createWebServer(); } catch (Throwable var2) {   }}//ServletWebServerApplicationContext.java//这里是创建webServer,但是还没有启动tomcat,这里是通过ServletWebServerFactory创建,那么接着看下ServletWebServerFactoryprivate void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = this.getServletContext(); if (webServer == null && servletContext == null) {  ServletWebServerFactory factory = this.getWebServerFactory();  this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); } else if (servletContext != null) {  try {   this.getSelfInitializer().onStartup(servletContext);  } catch (ServletException var4) {    } } this.initPropertySources();}//接口public interface ServletWebServerFactory {    WebServer getWebServer(ServletContextInitializer... initializers);}//实现AbstractServletWebServerFactoryJettyServletWebServerFactoryTomcatServletWebServerFactoryUndertowServletWebServerFactory

这里ServletWebServerFactory接口有4个实现类

如何在SpringBoot中启动tomcat

而其中我们常用的有两个:TomcatServletWebServerFactory和JettyServletWebServerFactory。

//TomcatServletWebServerFactory.java//这里我们使用的tomcat,所以我们查看TomcatServletWebServerFactory。到这里总算是看到了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 connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) {  tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers); return getTomcatWebServer(tomcat);}protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { return new TomcatWebServer(tomcat, getPort() >= 0);} //Tomcat.java//返回Engine容器,看到这里,如果熟悉tomcat源码的话,对engine不会感到陌生。public Engine getEngine() {    Service service = getServer().findServices()[0];    if (service.getContainer() != null) {        return service.getContainer();    }    Engine engine = new StandardEngine();    engine.setName( "Tomcat" );    engine.setDefaultHost(hostname);    engine.setRealm(createDefaultRealm());    service.setContainer(engine);    return engine;}//Engine是最高级别容器,Host是Engine的子容器,Context是Host的子容器,Wrapper是Context的子容器

getWebServer这个方法创建了Tomcat对象,并且做了两件重要的事情:把Connector对象添加到tomcat中,configureEngine(tomcat.getEngine());
           getWebServer方法返回的是TomcatWebServer。

//TomcatWebServer.java//这里调用构造函数实例化TomcatWebServerpublic TomcatWebServer(Tomcat tomcat, boolean autoStart) { Assert.notNull(tomcat, "Tomcat Server must not be null"); this.tomcat = tomcat; this.autoStart = autoStart; initialize();}private void initialize() throws WebServerException {    //在控制台会看到这句日志 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())) {     removeServiceConnectors();    }   });   //===启动tomcat服务===   this.tomcat.start();   rethrowDeferredStartupExceptions();   try {    ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());   }   catch (NamingException ex) {                   }                        //开启阻塞非守护进程   startDaemonAwaitThread();  }  catch (Exception ex) {   stopSilently();   destroySilently();   throw new WebServerException("Unable to start embedded Tomcat", ex);  } }}//Tomcat.javapublic void start() throws LifecycleException { getServer(); server.start();}//这里server.start又会回到TomcatWebServer的public void stop() throws LifecycleException { getServer(); server.stop();}
//TomcatWebServer.java//启动tomcat服务@Overridepublic void start() throws WebServerException { synchronized (this.monitor) {  if (this.started) {   return;  }  try {   addPreviouslyRemovedConnectors();   Connector connector = this.tomcat.getConnector();   if (connector != null && this.autoStart) {    perfORMDeferredLoadOnStartup();   }   checkThatConnectorsHaveStarted();   this.started = true;   //在控制台打印这句日志,如果在yml设置了上下文,这里会打印   logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"     + getContextPath() + "'");  }  catch (ConnectorStartFailedException ex) {   stopSilently();   throw ex;  }  catch (Exception ex) {   throw new WebServerException("Unable to start embedded Tomcat server", ex);  }  finally {   Context context = findContext();   ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());  } }}//关闭tomcat服务@Overridepublic void stop() throws WebServerException { synchronized (this.monitor) {  boolean wasStarted = this.started;  try {   this.started = false;   try {    stopTomcat();    this.tomcat.destroy();   }   catch (LifecycleException ex) {       }  }  catch (Exception ex) {   throw new WebServerException("Unable to stop embedded Tomcat", ex);  }  finally {   if (wasStarted) {    containerCounter.decrementAndGet();   }  } }}

附:tomcat顶层结构图

如何在SpringBoot中启动tomcat

      tomcat最顶层容器是Server,代表着整个服务器,一个Server包含多个Service。从上图可以看除Service主要包括多个Connector和一个Container。Connector用来处理连接相关的事情,并提供Socket到Request和Response相关转化。Container用于封装和管理Servlet,以及处理具体的Request请求。那么上文提到的Engine>Host>Context>Wrapper容器又是怎么回事呢? 我们来看下图:

如何在SpringBoot中启动tomcat

      综上所述,一个tomcat只包含一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但有多个Connector,这样一个服务可以处理多个连接。
      多个Connector和一个Container就形成了一个Service,有了Service就可以对外提供服务了,但是Service要提供服务又必须提供一个宿主环境,那就非Server莫属了,所以整个tomcat的声明周期都由Server控制。

关于如何在SpringBoot中启动tomcat问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: 如何在SpringBoot中启动tomcat

本文链接: https://www.lsjlt.com/news/275635.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • 如何在SpringBoot中启动tomcat
    如何在SpringBoot中启动tomcat?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。springboot是什么springboot一种全新的编程规范,其设计目的是用来...
    99+
    2023-06-14
  • Tomcat中怎么启动SpringBoot
    这篇文章给大家介绍Tomcat中怎么启动SpringBoot,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。从 Main 方法说起用过SpringBoot的人都知道,首先要写一个main方法来启动@SpringBootA...
    99+
    2023-06-16
  • Tomcat中SpringBoot应用无法启动如何解决
    Tomcat中SpringBoot应用无法启动如何解决?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。问题描述我修改pom.xml将打包方式改成war<packagin...
    99+
    2023-05-31
    springboot omc tomcat
  • springboot中如何利用Tomcat容器实现自启动
    这篇“springboot中如何利用Tomcat容器实现自启动”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springbo...
    99+
    2023-06-08
  • 如何在Spring Boot中内嵌Tomcat并启动
    本篇文章给大家分享的是有关如何在Spring Boot中内嵌Tomcat并启动,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。createEmbeddedServletConta...
    99+
    2023-05-31
    springboot tomcat omc
  • 怎么在Eclipse中启动Tomcat
    要在Eclipse中启动Tomcat,您需要遵循以下步骤:1. 确保您已经安装了Eclipse和Tomcat。如果还没有安装,请先下...
    99+
    2023-09-14
    Tomcat
  • tomcat怎么启动springboot项目
    要启动Spring Boot项目,可以使用Tomcat来进行部署。以下是启动Spring Boot项目的步骤:1. 首先,确保你的S...
    99+
    2023-10-10
    tomcat springboot
  • Linux如何启动tomcat服务
    这篇文章主要介绍了Linux如何启动tomcat服务,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。tomcat是随机启动的,所以在开启服务器的时候要手动开启tomcat,不然...
    99+
    2023-06-28
  • 如何用tomcat启动项目
    以下是使用Tomcat启动项目的步骤:1. 确保你已经安装了Tomcat服务器,并配置好了JAVA_HOME环境变量。2. 将你的项...
    99+
    2023-09-23
    tomcat
  • springboot启动报错Unable to start embedded Tomcat
    这个错误通常是由于端口冲突或者Tomcat配置错误导致的。以下是一些可能的解决方案:1. 检查端口是否被占用:可以使用以下命令查看系...
    99+
    2023-09-08
    springboot
  • Linux系统如何启动Tomcat
    Linux系统如何启动Tomcat,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Tomcat 简介:一、概念  Tomcat 服务器是一个开源的轻量级Web应用服...
    99+
    2023-06-28
  • tomcat启动慢如何解决
    要解决Tomcat启动慢的问题,可以尝试以下方法:1. 调整JVM参数:在启动脚本(如catalina.sh或catalina.ba...
    99+
    2023-08-30
    tomcat
  • SpringBoot Tomcat启动实例代码详解
    废话不多了,具体内容如下所示:Application configuration class:@SpringBootApplicationpublic class ServletInitializer extends SpringBootS...
    99+
    2023-05-31
    spring boot tomcat
  • springboot使用外置tomcat启动方式
    目录使用外置tomcat启动使用外置的tomcat启动注意事项 使用外置tomcat启动 打开pom文件,把打包格式设置为war <packaging>war<...
    99+
    2024-04-02
  • SpringBoot内置tomcat启动原理详解
    前言 不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcat在spring...
    99+
    2024-04-02
  • 传统tomcat启动服务与springboot启动内置tomcat服务的区别(推荐)
    spring整合springmvc  spring整合springmvc中web.xml配置如下,tomcat在启动过程中会加载web.xml中的内容,Conte...
    99+
    2024-04-02
  • linux如何设置tomcat自启动
    这篇文章主要介绍“linux如何设置tomcat自启动”,在日常操作中,相信很多人在linux如何设置tomcat自启动问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux如何设置tomcat自启动”的疑...
    99+
    2023-07-05
  • idea中tomcat启动不起来如何解决
    当Tomcat无法启动时,可以尝试以下解决方法:1. 检查端口冲突:确保Tomcat使用的端口没有被其他程序占用。可以使用命令`ne...
    99+
    2023-09-12
    tomcat idea
  • tomcat启动报错如何解决
    当Tomcat启动时报错,解决方法通常包括以下步骤:1. 检查Tomcat日志:查看Tomcat启动日志(通常位于Tomcat安装目...
    99+
    2023-09-13
    tomcat
  • tomcat如何启动jar包项目
    要在Tomcat上启动一个包含jar包的项目,需要将jar包添加到项目的类路径中,并将项目部署到Tomcat的webapps目录中。...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作