Spring Boot War部署到Tomcat


73

我试图将Spring Boot应用程序部署到Tomcat,因为我想部署到AWS。我创建了一个WAR文件,但是即使它可见,它似乎也不能在Tomcat上运行。

详细信息:
0。这是我的应用程序:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class App {
    public static void main(String[] args) {
        SpringApplication.run(SampleController.class, args);
    }
}

@Controller
@EnableAutoConfiguration
public class SampleController {
    @RequestMapping("/help")
    @ResponseBody
    String home() {
        String input = "Hi! Please use 'tag','check' and 'close' resources.";
        return input;
    }
}

application.properties具有以下内容:

server.port=${port:7777}
  1. 在阅读了许多页面问题解答之后,我在POM中添加了以下内容:

    http://maven.apache.org/xsd/maven-4.0.0.xsd“> 4.0.0

    <groupId>com.niewlabs</groupId>
    <artifactId>highlighter</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <packaging>war</packaging>
    
    <properties>
        <java.version>1.8</java.version>
    </properties>    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    

  2. 我运行了“ mvn软件包”,并得到了WAR文件(大小为250Mb),并将其放入“ webapps”文件夹中。

  3. 我启动了Tomcat,并能够看到列出的应用程序,在本例中为“ /highlighter-1.0-SNAPSHOT”。
  4. 单击应用程序的链接将显示“状态404”页面。
  5. 当我单独运行Spring Boot应用程序而没有容器时,它运行在localhost:7777上,但是当我在Tomcat中运行它时却什么也没有。

更新:还有另一个参考。不知道它有多有用。


4
您扩展SpringBootServletInitializer并覆盖了它的configure方法吗?
安迪·威尔金森

不,我在Spring Guide WAR说明中没有看到任何提及。您能给我一个链接或详细信息吗?
Daniil Shevelev 2015年

2
@AndyWilkinson谢谢您的提示。我在《 Spring Guide》 [ docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/…中找到了答案。但是我的应用程序仍然无法在Tomcat上运行。
Daniil Shevelev 2015年

我遵循了文档的所有步骤,但仍然是404。从tomcat本地主机日志中,似乎已检测到应用程序。09-Nov-2019 11:19:59.676 INFO [main] org.apache.catalina.core.ApplicationContext.log 1 Spring WebApplicationInitializers detected on classpath 09-Nov-2019 11:20:12.722 INFO [main] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized()
阿贾伊·亚达夫

@AjayYadav您如何解决的?
复员

Answers:


106

本指南详细说明了如何在Tomcat上部署Spring Boot应用程序:http :
//docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file

本质上,我需要添加以下类:

public class WebInitializer extends SpringBootServletInitializer {   
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
    }    
}

我还向POM添加了以下属性:

<properties>        
    <start-class>mypackage.App</start-class>
</properties>

7
我将更新对以下内容的引用-docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… “将jar转换为war maven”部分仅指向您的引用中的嵌入式版本。总之感谢
nickolay.laptev'Aug

此修复程序对我有用!我可以确认文档已按照上面的注释中的建议进行了更新。docs.spring.io/spring-boot/docs/current/reference/htmlsingle/...
米格尔·雷耶斯

2
我不确定是否需要添加<start-class>属性。我的配置不需要它,参考文档中也没有提及。
新泽西州的LJ

由于该应用程序在没有此“ ServeletInitializer”文件的情况下在STS中运行,因此我带着荣耀删除了该文件,并用了两天的时间敲了一下头,想知道为什么它不能在Tomcat上运行。感谢您的回答。通过查看这个Servlet名称,我想起了我的错误,并且在将文件替换回后,它已得到修复。
学习者

对于我来说,运行Spring Boot 2.1不需要<start-class>。
阿古斯特·桑切斯

24

嘿,请确保对pom.xml进行此更改

<packaging>war</packaging>

在“依赖项”部分中,请确保指示提供了tomcat,因此您不需要嵌入的tomcat插件。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>       

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>       

这就是整个pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <start-class>com.example.Application</start-class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>       

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>       

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

而且Application类应该像这样

应用程序

package com.example;

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 Application extends SpringBootServletInitializer {


    /**
     * Used when run as JAR
     */
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    /**
     * Used when run as WAR
     */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Application.class);
    }

}

您可以添加一个控制器来测试MyController.java

package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @RequestMapping("/hi")
    public @ResponseBody String hiThere(){
        return "hello world!";
    }
}

然后,您可以在tomcat 8版本中运行项目并像这样访问控制器

http:// localhost:8080 / demo / hi

如果由于某种原因您无法将项目添加到tomcat,请右键单击该项目,然后转到“构建路径”->“配置构建路径”->“ Project Faces”

确保仅选择这3个

动态网络模块3.1 Java 1.8 Javascript 1.0


21

我认为您对这里的不同范例感到困惑。首先,war文件和服务器部署-这些东西属于Java Enterprise Edition(Java EE)。这些概念在采用不同模型的spring-boot应用程序中没有实际位置。

Spring-boot负责创建一个嵌入式容器,并直接从标准jar文件中运行您的服务(尽管它可以做很多事情)。我认为该模型的目的是支持微服务开发-每个服务都有自己的容器,并且完全独立。您也可以使用代码来生成Java EE应用程序,但是考虑到spring-boot容易得多(对于某些类型的应用程序/服务),这将是很愚蠢的。

因此,鉴于此信息,您现在必须确定要遵循的范式,并且仅需要遵循该范式。

Spring-boot是可执行的-您只需要运行App类中的main方法,即可从命令行或使用您喜欢的IDE或maven或gradle(提示:maven是正确的答案)来运行。这将启动一个tomcat服务器(默认情况下),并且您的服务将在其中可用。鉴于您在服务上方发布的配置应该可以在以下位置使用:http://localhost:7777/context/help-context用来替换您尚未共享的上下文名称。

您并不是要发动战争,运行tomcat或部署任何东西。在spring-boot中,这些都不是必需的。在你的POM的包装应该是jar,不warscopespring-boot-starter-tomcat应该被删除-它肯定是不提供的。

运行main方法时,控制台输出应告诉您已注册的上下文;使用它来获取正确的URL。

综上所述,spring-boot必须暂时存在于JEE世界中(直到被广泛采用)。因此,春季人们已经记录了一种用于构建战争而不是可执行jar的方法,以便部署到servlet或JEE容器中。这使得许多弹簧靴技术可以用于禁止使用战争(或耳朵)以外的任何东西的环境。但是,这只是对以下事实的回应:这样的环境非常普遍,而不被视为解决方案的必要或什至理想的一部分。


5
我希望避免部署到Tomcat,但这似乎是将应用程序部署到AWS的最简单方法。
Daniil Shevelev 2015年

2
不,使用spring-boot和docker-这是在包括AWS在内的任何地方进行部署的最简单方法(请相信我-我是从经验出发)
软件工程师


4
我不认为这在结构上是正确的。Spring Boot确实允许将war文件部署到容器中。但是对于大多数用例来说,这是正确的。因此,我很想赞成和反对这个问题。见docs.spring.io/spring-boot/docs/current/reference/html/...
韦斯

2
如果您已经在tomcat上运行了一堆现有的经典spring应用程序,那么spring boot war文件部署是开始使用spring boot的好方法,而无需一次更改太多。
jkerak

6

您的Application.java班级应该扩展SpringBootServletInitializer班级,例如:

public class Application extends SpringBootServletInitializer {}

4

使用Gradle的人的解决方案

将插件添加到 build.gradle

apply plugin: 'war'

提供的依赖项添加到tomcat

dependencies {
    // other dependencies
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}

3

遵循指南(或使用Spring Initializr)之后,我有一个可以在本地计算机上运行的WAR,但不能在远程上运行(在Tomcat上运行)。

没有错误消息,它只是说“找到了Spring servlet初始化程序”,但什么也没做。

17-Aug-2016 16:58:13.552 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.4
17-Aug-2016 16:58:13.593 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /opt/tomcat/webapps/ROOT.war
17-Aug-2016 16:58:16.243 INFO [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

17-Aug-2016 16:58:16.301 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log 2 Spring WebApplicationInitializers detected on classpath
17-Aug-2016 16:58:21.471 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext
17-Aug-2016 16:58:25.133 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized()
17-Aug-2016 16:58:25.133 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log SessionListener: contextInitialized()

没事了 Spring Boot只是没有运行。

显然,我使用Java 1.8编译了服​​务器,而远程计算机具有Java 1.7。

用Java 1.7编译后,它开始工作。

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.7</java.version> <!-- added this line -->
    <start-class>myapp.SpringApplication</start-class>
</properties>

3

公共类应用程序扩展了SpringBootServletInitializer {}

只是扩展了SpringBootServletInitializer。它将在您的AWS / tomcat中工作


1
您能否弄清您的答案带来了什么,而您的答案却比您的答案早了三个小时才出现,或者您无法接受2015年以来的答案?
Foon

3

我遇到了同样的问题,请按照本指南找出解决方案。我在Maven中有目标地奔跑。

清洁包装

它为我工作


1

使用Spring Boot 1.5.8.RELEASE更新2018-02-03

在pom.xml中,需要通过将包更改为war来告知Spring插件何时构建它是war文件,如下所示:

<packaging>war</packaging>

另外,在构建软件包时,您还必须通过添加以下代码来排除嵌入式tomcat:

    <!-- to deploy as a war in tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

完整的可运行示例在此处 https://www.surasint.com/spring-boot-create-war-for-tomcat/


3
那还不够。主Application类必须实现SpringBootServletInitializer以便与容器执行和独立执行兼容。Op的示例丢失了它。
Aram Paronikyan

0

如果您的目标是将Spring Boot应用程序部署到AWSBoxfuse将为您提供一个非常简单的解决方案。

您需要做的是:

boxfuse run my-spring-boot-app-1.0.jar -env=prod

这将:

  • 融合为您的应用量身定制的最小化OS映像(比典型的Linux发行版小约100倍)
  • 将其推送到安全的在线存储库
  • 大约30秒即可将其转换为AMI
  • 创建和配置新的Elastic IP或ELB
  • 给它分配一个新域名
  • 根据您的新AMI启动一个或多个实例

所有图像均以秒为单位生成并且不可变。它们可以在VirtualBox(dev)和AWS(test&prod)上不变地运行。

所有更新均作为零停机时间的蓝色/绿色部署执行,您还可以仅使用一个命令来启用自动缩放。

Boxfuse还了解您的Spring Boot配置将根据您的application.properties配置自动配置安全组和ELB健康检查

这是帮助您入门的教程:https : //boxfuse.com/getstarted/springboot

免责声明:我是Boxfuse的创始人兼首席执行官


0

如果要创建新应用程序而不是转换现有应用程序,则创建基于WAR的Spring Boot应用程序的最简单方法是通过Spring Initializr

它会自动为您生成应用程序。默认情况下,它将创建Jar,但是在高级选项中,您可以选择创建WAR。这场战争也可以直接执行。

在此处输入图片说明

更容易的是直接从IntelliJ IDEA创建项目:

文件→新建项目→Spring Initializr

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.