专栏首页Java深度编程SpringBoot解决内、外tomcat部署兼容问题

SpringBoot解决内、外tomcat部署兼容问题

前言:

我们在使用springBoot开发的过程中出于方便,都会选择使用本地类Application中的main方法启动服务,即可实现本地的调试,十分的方便。但在线上环境需要放入外部的tomcat部署,这时候你会发现如果不做任何的处理是无法在外部tomcat启动的。

那么如何才能让springBoot项目才能在外部tomcat部署呢?这就涉及到启动入口,spring上下文对象的问题,我们本地之所以能通过main方法作为启动,是因为springBoot提供了一个此方式的上下文对象作为适配,通过SpringApplication.run调用了这个入口,进而使用内部的tomcat实现了服务的部署。之所以直接丢在外部tomcat无法启动,就是因为入口不同,驱动的时候做了适配的上下文。简而言之,入口是第一要素。所以既然外部tomcat启动没有入口,那我们就给它造一个入口。

实现外部的tomcat入口需要继承SpringBootServletInitializer,并重写configure方法,如下:

@SpringBootApplication
public class DemoApplication  extends SpringBootServletInitializer {

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

  /**
   *提供外部tomcat启动入口
   */
  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    // 注意这里要指向原先用main方法执行的Application启动类
    return builder.sources(DemoApplication.class);
  }
}

或者你可以新建一个类,与原Application类分开,如下:

以上就是实现外部tomcat入口的方式,按此方式即可实现外部tomcat部署了。

在网上有很多人写博客都指出了要排除web包下的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>

如果你真的这么做了以后,你就被坑了。你会发现,虽然外部tomcat能部署了,但无法再同步本地java的main方法部署了,那么开发环境,和线上环境将会变得很麻烦。往往这些写这种博客的人只稀里糊涂的说要移除这个web包下的tomcat,却又不告诉你怎么解决本地无法启动的问题。之所以本地无法启动正是因为tomcat被移除了,没有了tomcat你还怎么启动呢!所以这时候就会又有文章来告诉你,要再加一个tomcat:

<!--spring-boot 内嵌tomcat主依赖, 方便本地调试
        (移除web包下的tomcat后需要此包本地才能启动)-->
    <!--兼容继承SpringBootServletInitializer外部tomcat启用-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>1.5.9.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

这些解决方案在网上都能找到,但鲜有人告诉你这其中的本质是什么,看到这些文章的人总会以为是因为要兼容外部的tomcat,所以要移除本地的tomcat,如果你这么想就错了。你反过来想想也就明白了,如果web包下的tomcat能引起和外部tomcat的冲突,那么又导入了spring-boot-starter-tomcat怎么就没冲突呢!事实说明其实根本就不存在所谓的冲突!前面说过部署的第一关是入口,入口不同使用了不同的适配上下文对象,所以它们是不会冲突的。

也就是说其实根本就不需要导入spring-boot-starter-tomcat,只要不排除web包下的tomcat,依然能够实现本地main方法,和外部tomcat的部署的兼容性问题。

而还有些项目中既没有排除web包下的tomcat,又同时导入了spring-boot-starter-tomcat,同样也能实现本地main方法,和外部tomcat的部署,这又是怎么回事呢?很多人很疑惑存在两个tomcat不会冲突吗?加上外部部署的tomcat就三个tomcat了,为何能够实现兼容?

首先前面说过内部与外部tomcat部署的入口不同,上下文的适配不同,因此不会冲突,那又该怎么解释内部的两个tomcat也不冲突呢?这就要说到maven依赖传递的问题了。

在maven有直接依赖和间接依赖这两种,A依赖B,B依赖C,那么A直接依赖B,B直接依赖C,而A则是间接依赖C,那么他们之间的依赖就有一条路线 A --> B --> C,此路线被称为依赖路径,如果遇到相同的依赖,则根据路径最短优先

也就是说根据上面的规则,假如再出现一个依赖C2,且C2 = C,具有C一样的功能和类,并且A依赖C2,那么当A需要C下的功能时,它有两个选择C和C2这时候有两条路径 1.A --> B --> C ; 2. A --> C2 。规则路径最短优先原则,那么A会选择C2作为依赖选取,从而遗弃C。这也就能解释为什么web下的tomcat和导入的spring-boot-starter-tomcat为什么能够共存而不引起冲突,那是因为压根就轮不到web下的tomcat起作用,当导入了spring-boot-starter-tomcat后,有没有web下的tomcat已经无所谓了,所以你排不排除它都没关系了。

本文分享自微信公众号 - Java深度编程(JavaDeep),作者:龚文学

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 多线程编程必备技术—— volatile,synchronized,lock

    volatile: volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。确保本条指令不会...

    Java深度编程
  • 如何将文件内容转成String字符串

    以上两种方式从编码简洁度来讲,肯定是第二种好很多,但其实性能是差不多的,一个是牺牲了读的性能,另一个是牺牲了写的性能。

    Java深度编程
  • 玩转mysql函授:concat以及group_concat

    返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。

    Java深度编程
  • Tomcat进阶操作

    这个文件的内容可以效仿系统自带的manager页面认证的配置文件/application/tomcat/webapps/manager/WEB-INF/web....

    山山仙人
  • CentOS下部署JDK+Tomcat8

    1、Tomcat需要JDK环境,参考之前的文章CentOS6下安装Java JDK8,提前安装好JDK环境

    yuanfan2012
  • Web基础配置篇(三): tomcat的配置及使用

    tomcat,大家应该都知道是啥,servlet的Web容器而已,遵守servlet规范的JavaEE服务器。我们通常用tomcat来部署war包来做应用服务器...

    品茗IT
  • 将 java 项目部署到 linux 上的具体步骤

    项目部署其实非常的简单,尤其是 java 项目。最近微信群里有网友,初学者还未毕业,问我 Java 项目是如果部署的?

    业余草
  • 第九章 tomcat配置

    上一章,我们介绍了apache服务的部署,其中我们介绍过网页开发所用到的语言,以asp、jsp、php为主,我们已经演示过php页面的使用。本章我们将演示jsp...

    晓天
  • Web基础配置篇(三): tomcat的配置及使用

    tomcat,大家应该都知道是啥,servlet的Web容器而已,遵守servlet规范的JavaEE服务器。我们通常用tomcat来部署war包来做应用服务器...

    品茗IT
  • Linux 环境定时重启 tomcat

    亲手搭建的博客系统经常会宕机,一直想着定时检测tomcat服务挂掉之后进行重启操作。昨天终于有时间,就把这个事情做了一下,最终可以正常工作。本篇就记录一下我解决...

    不安分的猿人

扫码关注云+社区

领取腾讯云代金券