Spring 启动 War 部署到 Tomcat

Spring Boot War deployed to Tomcat

我正在尝试将 Spring 启动应用程序部署到 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. 在阅读了一些 pages and question-answers 之后,我在我的 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 package" 得到 WAR 文件(大小 250Mb),我将其放入 "webapps" 文件夹。

  3. 我开始 Tomcat 并且能够看到列出我的应用程序,在我的例子中是“/highlighter-1.0-SNAPSHOT”。
  4. 单击应用程序的 link 会出现 "Status 404" 页面。
  5. 当我 运行 Spring 单独启动应用程序,没有容器它 运行 在 localhost:7777 上,但是当我 运行 它在 Tomcat。

更新: 还有一个reference。不确定它有多大用处。

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

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

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

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

您并不打算创建 war、运行宁 tomcat 或部署任何东西。 None 在 spring-boot 中是必需的。您的 pom 中的包装应该是 jar,而不是 warspring-boot-starter-tomcatscope 应该被删除——当然没有提供。

当你 运行 你的 main 方法时,控制台输出应该告诉你你已经注册的上下文;用它来获得 URL 的权利。

话虽如此,spring-boot 目前必须存在于 JEE 世界中(直到它被广泛采用)。出于这个原因,spring 人员记录了一种构建 war 而不是可执行 jar 的方法,用于部署到 servlet 或 JEE 容器。这使得许多 spring-boot 技术可以在限制使用 wars(或耳朵)以外的任何东西的环境中使用。然而,这只是对这样的环境非常普遍这一事实的回应,并不被视为解决方案的必要甚至不可取的部分。

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

基本上我需要添加以下内容 class:

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>

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

您只需:

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

这将:

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

所有图像都在几秒钟内生成并且是不可变的。它们可以 运行 在 VirtualBox (dev) 和 AWS (test & prod) 上保持不变。

所有更新都作为 零停机时间 blue/green 部署 执行,您还可以仅使用一个命令启用自动缩放。

Boxfuse 还了解您的 Spring 启动配置将 根据您的 application.properties.

自动配置安全组和 ELB 健康检查

这里有一个教程可以帮助您入门:https://boxfuse.com/getstarted/springboot

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

按照指南(或使用 Spring Initializr)后,我有一个 WAR 在我的本地计算机上工作,但不能远程工作(运行ning 在 Tomcat).

没有错误信息,只是说"Spring servlet initializer was found",但什么也没做。

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 只是没有启动 运行。

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

用Java1.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>

您的 Application.java class 应该扩展 SpringBootServletInitializer class 例如:

public class Application extends SpringBootServletInitializer {}

public class 应用程序扩展 SpringBootServletInitializer {}

只是扩展了 SpringBootServletInitializer。它适用于您的 AWS/tomcat

嘿,请务必对 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>

应用class应该是这样的

Application.java

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 Java脚本 1.0

我遇到了同样的问题,我按照这个 guide 找到了解决方案。我 运行 在 maven 中有目标。

clean package

它对我有用 Thanq

针对 Gradle

用户的解决方案

将插件添加到 build.gradle

apply plugin: 'war'

provided 依赖添加到 tomcat

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

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

在 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/

如果您要创建新应用而不是转换现有应用,创建基于 WAR 的 spring 启动应用的最简单方法是通过 Spring Initializr.

它auto-generates适合您的应用程序。默认情况下它会创建 Jar,但在高级选项中,您可以 select 创建 WAR。这个war也可以直接执行

直接从 IntelliJ IDEA 创建项目更简单:

File → New Project → Spring Initializr

TL;DR:

  • Make sure you have the same Tomcat version in your application dependency, and the external tomcat installation
  • Have the same Java version

我已按照所有步骤制作 Spring 引导应用程序,以生成与外部 Tomcat 服务器兼容的 WAR。我也扩展了 SpringBootServletInitializer。如果您还没有这样做,请先按照其他答案或 Official Spring Docs - Traditional Deployment

中的说明进行这些更改

应用程序 运行 在 STS Embedded Tomcat 上运行良好,但在外部 Tomcat 中会给出 404 - Not Found。没有错误,catalina.bat run 命令也给出了信息“war 的部署已完成”。

14-Apr-2021 12:38:01.996 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
14-Apr-2021 12:38:01.996 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/10.0.5]
14-Apr-2021 12:38:02.023 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [C:\dev\apache-tomcat-10.0.5\webapps\server-test-1-0.0.1-SNAPSHOT.war]
14-Apr-2021 12:38:05.349 INFO [main] 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.
14-Apr-2021 12:38:05.436 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [C:\dev\apache-tomcat-10.0.5\webapps\server-test-1-0.0.1-SNAPSHOT.war] has finished in [3,413] ms

但通常,Spring与启动相关的输出(如 Initializing Spring DispatcherServlet 'dispatcherServlet')也应该出现在此 Catalina 控制台上。但这并没有出现。

我的问题是: 我的 Maven 依赖文件夹中有 tomcat-embed-core-9.0.44。但是我在我的机器上安装了独立 Tomcat 版本 10.x.xx。

我在我的机器上安装了 Tomcat 版本 9.0.xx,应用程序运行良好。