1.springboot 的内置tomcat没有去掉,导致springboot 和tomcat 分别启动了1次

2.完全是tomcat 启动了两次

第一个问题:我们在springboot pom.xml中

<packaging>war</packaging>  
<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的依赖-->  
<dependency>  
  <groupId>javax.servlet</groupId>  
  <artifactId>javax.servlet-api</artifactId>  
  <version>3.1.0</version>  
  <scope>provided</scope>  
</dependency>


第二个问题:在tomcat 的server.xml中 把host的appBase 换为“”,然后启动就好了

或者你在tomcat内部新建一个webroot 文件夹 然后把appBase换成webroot 也可以

就是host 和context 分别启动了两次

 

当时看到这的时候以为肯定是这两个问题,一定能解决,结果我们改完之后,测试还是不好使

然后经过测试

发现是springboot 启动类 @SpringBootApplication的类 把extends 的去掉就好了

具体原因就不在这里说明了,但是基本上springboot 在tomcat 中发布两次的问题 就这三个原因了

原文链接:

 

 

 

idea中使用tomcat 方式启动spring boot项目

 

 Spring boot 的main 入口启动方式相信都会用,直接运行main直接就启动了,但是往往这种方式并不是最佳的启动方式,比如运维的层面更希望调整tomcat的调优参数,而只使用嵌入启动方式很难做到这些。所以使用tomcat方式启动spring boot就比较重要。

 

1、去tomcat 官网下载 tomcat 8 tar.gz 文件,然后解压.

 https://tomcat.apache.org/download-80.cgi

2、idea中,配置启动

 

spring boot 执行2次 springboot启动两次的问题_spring

 

spring boot 执行2次 springboot启动两次的问题_spring_02


spring boot 执行2次 springboot启动两次的问题_xml_03

3、gradle or maven 配置

<packaging>war</packaging>

or

apply plugin: "war"

 

4、增加tomcat启动调用spring boot初始化入口:

spring boot 执行2次 springboot启动两次的问题_xml_04

public class ServletInitializer extends SpringBootServletInitializer {

    private Logger logger = LoggerFactory.getLogger(ServletInitializer.class);

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {

        logger.info("starting spring boot initializer ......");

        return application.sources(MainApplication.class);
    }

}

spring boot 执行2次 springboot启动两次的问题_xml_04

 or

spring boot 执行2次 springboot启动两次的问题_xml_04

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

spring boot 执行2次 springboot启动两次的问题_xml_04

 

5、start runing

 搞定!

 

 

 

 

 

 

tomcat重启两次的原因是appBase和Context中docBase设置的值导致的,只需要把appBase置为空,docBase写项目的绝对路径就可以了,代码如下:

<Host name="localhost" appBase=""
            unpackWARs="true" autoDeploy="true">
		<Context path="/" docBase="F:/Tomcat8.5/webroot/taocloud" debug="0"/>        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />      </Host>


————————————————

Java代码  

spring boot 执行2次 springboot启动两次的问题_tomcat_08

1. <Host name="localhost"  appBase=""  
2. "true" autoDeploy="true"  
3. "false" xmlNamespaceAware="false">  
4.   
5. "/usr/local/apache-tomcat-6.0.29/webapps/semwinner"  path=""   reloadable="true"></Context>  
6. "/usr/local/apache-tomcat-6.0.29/webapps/emarboxmanager"  path="/admin"   reloadable="true"></Context>  
7.   
8.      </Host>

 把appBase设置为空即可!

去除了appBase="webapps"中的webapps变成了appBase="",因为web应用程序都是放在webapps这个目录下的,如果 不把“webapps“去掉,这里会调用一次quartz的任务调度,在接下来的“<Context path”中又会调用一次quartz的任务调度,所以就重复了2次

 

 https://www.iteye.com/blog/nkliuliu-816335

 

 

 

本人这个问题最后解决发现,的确是由   web应用程序默认都是放在webapps这个目录下的,如果不把“webapps“去掉,这里会调用一次quartz的任务调度,在接下来的“<Context path”中又会调用一次quartz的任务调度  这个原因导致。

而且本人刚开始执行3次,tomcat的webapp下面XXX.WAR包解压之后,war包没有删除,相当webapp目录下有 XXX 和XXX.war 所以XXX和XXX.war各执行一次,当删除XXX.war时,就只执行了2次,分别是 tomcat的server.xml中appBase和Context docBase,再删除

<Context docBase=   就只执行一次了。

以上本人验证成功!

如果webapp下面有多个不同的war包,那么把server.xml中appBase 的内容去掉,应该也是可以。这点没试过,待验证!


 

我开始以为眼花了,tomcat启动的时候,

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.2.RELEASE)

出现了两次,然后日志中有报错:

 Unable to register MBean [HikariDataSource (HikariPool-2)] with key 'dataSource ...

最终确认springboot被加载了两次。

原因一:

war包发布,可能没有排除内置tomcat,先确认exclusions

spring boot 执行2次 springboot启动两次的问题_xml_09

 

原因二:

tomcat的server.xml配置有问题

如果<Context>节点里配置了应用全路径,那么<host>节点里的appBase要置空,否则就是这出问题,host和context分别加载一次。

spring boot 执行2次 springboot启动两次的问题_spring boot 执行2次_10

 

待测: 如果有两个springboot应用放在tomcat下的情况,还未测试。