【SpringBoot】部署至Tomcat容器后启动完成后自动关闭的问题

背景

首先说一下实践项目的形式:对外提供的API服务,无界面,无web.xml,打包方式:

war

问题说明

项目打包后,部署至Tomcat的webapps目录下,启动Tomcat,发现启动成功后,打印日志(INFO级别,非ERROR):

Unregistering JMX-exposed beans on shutdown

查看Tomcat状态:

jps

发现Tomcat未运行。

解决方案

问题原因: Tomcat容器和内置Tomcat冲突,即jar包冲突。
查看jar包:

cd tomcat/webapps
find . -name *tomcat*

发现有依赖jar包:

tomcat-embed-core-8.5.29.jar
tomcat-annotations-api.jar
tomcat-embed-el-8.5.29.jar

tomcat-jdbc-8.5.29.jar
tomcat-juli-8.5.29.jar

通过eclipse的Dependency Hierarchy,搜索tomcat关键字,发现前三个jar包属于spring-boot-starter-tomcat,后面俩依赖属于tomcat-jdbc

解决如下:



    org.springframework.boot
    spring-boot-starter-tomcat
    provided


    org.apache.tomcat
    tomcat-jdbc
    provided


Maven的Scope简介

mavenscope依赖范围的概念:
依赖范围就是用来控制依赖和三种classpath(编译classpath,测试classpath、运行classpath)的关系,Maven有如下几种依赖范围:

compile: 编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-code在编译、测试和运行的时候都需要使用该依赖

test: 测试依赖范围。使用次依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此依赖。典型的例子是Jnuit,它只有在编译测试代码及运行测试的时候才需要

provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时候无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器以及提供,就不需要Maven重复地引入一遍。

问题详解

在开发和测试过程中,使用的都是内置tomcat容器(存在于spring-boot-starter-web),但是部署到Tomcat容器中,就会出现冲突报错。

1) 继承SpringBootServletInitializer,修改应用启动方式:

外部容器部署的话,就不能依赖于Application的main函数了,而是要以类似于web.xml文件配置的方式来启动Spring应用上下文,此时我们需要在启动类中继承SpringBootServletInitializer并实现configure方法

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

@SpringBootApplication
public class WebApplication extends SpringBootServletInitializer {

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

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

这个类的作用与在web.xml中配置负责初始化Spring应用上下文的监听器作用类似,只不过在这里不需要编写额外的XML文件了。

2)移除对嵌入式Tomcat的依赖




   javax.servlet
   javax.servlet-api
   3.1.0
   provided


   org.springframework.boot
   spring-boot-starter-tomcat
   provided


   org.apache.tomcat
   tomcat-jdbc
   provided


3)打包方式

war

4)修改编译设置
方法一


  
    
      maven-war-plugin
      2.6
      
              
        false                        
      
    
  

方法二:版本3.0.0的插件 web.xml不存在问题,所以可以通过升级插件来解决问题


  maven-war-plugin
  3.0.0

5)上下文路径
打成的包的名称应该和application.yml

server.context-path=/api

保持一致


    test

如果不一样发布到tomcat的webapps下上下文会变化

如果想了解SpringBoot是如何帮我们省去web.xml的话,可以查看文章:
https://www.jianshu.com/p/3c94d7e76998?utm_source=oschina-app

你可能感兴趣的:(Spring)