将 WAR 部署到 Tomcat(Spring Boot + Angular)

Posted

技术标签:

【中文标题】将 WAR 部署到 Tomcat(Spring Boot + Angular)【英文标题】:Deploy WAR to Tomcat (Spring Boot + Angular) 【发布时间】:2020-06-17 16:48:42 【问题描述】:

我正在尝试将带有 WAR 打包的 Spring Boot 应用程序部署到 Tomcat 10。应用程序已成功部署,但是,当我尝试访问端点时,它会导致 404 Not Found

WAR 文件:application.war

http://localhost:8080/application/api/abc -> 404 Not Found (Spring Boot Endpoint)
http://localhost:8080/application/abc -> 404 Not Found (Angular URL which calls /api/abc)

Tomcat webapps/application 文件夹包含以下内容,index.html (Angular) 有 <base href="/">


正如here 所讨论的,我添加了一个类AppServletInitializer,它扩展了SpringBootServletInitializer,如下所示

@Configuration
public class AppServletInitializer extends SpringBootServletInitializer 
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(SpringApp.class);
    
 

pom.xml中,我添加了spring-boot-starter-tomcat、tomcat-embed-jasper的依赖并设置包装选项为war。我已经分享了简化版(删除了依赖项、插件。如果需要,将添加相同的内容)

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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.name</groupId>
    <artifactId>application</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>My Application</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath />
    </parent>

    <properties>
        <!-- Build properties -->
        <maven.version>3.3.9</maven.version>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <project.testresult.directory>$project.build.directory/test-results</project.testresult.directory>
        <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
        <maven.compiler.source>$java.version</maven.compiler.source>
        <maven.compiler.target>$java.version</maven.compiler.target>
        <argLine>-Djava.security.egd=file:/dev/./urandom -Xmx256m</argLine>
        <m2e.apt.activation>jdt_apt</m2e.apt.activation>
        <run.addResources>false</run.addResources>

        <jhipster-dependencies.version>3.0.5</jhipster-dependencies.version>
        <spring-boot.version>2.1.8.RELEASE</spring-boot.version>
        <spring.version>5.1.9.RELEASE</spring.version>
        <hibernate.version>5.3.11.Final</hibernate.version>
        <javassist.version>3.23.2-GA</javassist.version>
        <maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
        <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
        <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
        <maven-war-plugin.version>3.2.3</maven-war-plugin.version>
        <properties-maven-plugin.version>1.0.0</properties-maven-plugin.version>
    </properties>


    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <finalName>application</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>$java.version</source>
                    <target>$java.version</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>$start-class</mainClass>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>$maven-compiler-plugin.version</version>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>$spring-boot.version</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-devtools</artifactId>
                    <optional>true</optional>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>prod</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-clean-plugin</artifactId>
                        <configuration>
                            <filesets>
                                <fileset>
                                    <directory>target/classes/static/</directory>
                                </fileset>
                            </filesets>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <configuration>
                            <mainClass>$start-class</mainClass>
                        </configuration>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-info</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <!--                    <plugin>-->
                    <!--                        <groupId>org.apache.maven.plugins</groupId>-->
                    <!--                        <artifactId>maven-war-plugin</artifactId>-->
                    <!--                        <version>$maven-war-plugin.version</version>-->
                    <!--                        <executions>-->
                    <!--                            <execution>-->
                    <!--                                <goals>-->
                    <!--                                    <goal>war</goal>-->
                    <!--                                </goals>-->
                    <!--                                <phase>package</phase>-->
                    <!--                            </execution>-->
                    <!--                        </executions>-->
                    <!--                        <configuration>-->
                    <!--                            &lt;!&ndash;<warSourceIncludes>WEB-INF/**,META-INF/**</warSourceIncludes>&ndash;&gt;-->
                    <!--                            <failOnMissingWebXml>false</failOnMissingWebXml>-->
                    <!--                        </configuration>-->
                    <!--                    </plugin>-->
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Application.java

import io.github.jhipster.config.JHipsterConstants;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.core.env.Environment;

@SpringBootApplication
@EnableConfigurationProperties(LiquibaseProperties.class, ApplicationProperties.class, AppServletInitializer.class)
public class Application extends SpringBootServletInitializer implements InitializingBean 

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    private final Environment env;

    public Application(Environment env) 
        this.env = env;
    

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

    @Override
    public void afterPropertiesSet() throws Exception 
        Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
        if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) 
            log.error("You have misconfigured your application! It should not run " +
                "with both the 'dev' and 'prod' profiles at the same time.");
        
        if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) 
            log.error("You have misconfigured your application! It should not " +
                "run with both the 'dev' and 'cloud' profiles at the same time.");
        
    


    public static void main(String[] args) 
        SpringApplication app = new SpringApplication(Application.class);
        DefaultProfileUtil.addDefaultProfile(app);
        Environment env = app.run(args).getEnvironment();
        logApplicationStartup(env);
    

    private static void logApplicationStartup(Environment env) 
        String protocol = "http";
        if (env.getProperty("server.ssl.key-store") != null) 
            protocol = "https";
        
        String serverPort = env.getProperty("server.port");
        String contextPath = env.getProperty("server.servlet.context-path");
        if (StringUtils.isBlank(contextPath)) 
            contextPath = "/";
        
        String hostAddress = "localhost";
        try 
            hostAddress = InetAddress.getLocalHost().getHostAddress();
         catch (UnknownHostException e) 
            log.warn("The host name could not be determined, using `localhost` as fallback");
        
        log.info("\n----------------------------------------------------------\n\t" +
                "Application '' is running! Access URLs:\n\t" +
                "Local: \t\t://localhost:\n\t" +
                "External: \t://:\n\t" +
                "Profile(s): \t\n----------------------------------------------------------",
            env.getProperty("spring.application.name"),
            protocol,
            serverPort,
            contextPath,
            protocol,
            hostAddress,
            serverPort,
            contextPath,
            env.getActiveProfiles());
    

application.yml

server:
  servlet:
    context-path: /application

我们在客户端使用 Angular,资源位于静态文件夹中。

环境: Spring Boot 2.1.8, 角8, Java 11,

我已经提到了,不幸的是,它们都不适合我。任何帮助将不胜感激

    Create a Deployable War File Spring Boot War Deploy Can not access deployed WAR file on Tomcat

【问题讨论】:

不是一个真正的答案,只是一个快速的想法:打开 start.spring.io 并创建一个“示例项目”,该项目会生成一个包含 WAR 和您的 java 和 spring boot 版本的工件。编译它并尝试在 tomcat 上部署,确保它按预期工作(这样您就可以确定 tomcat 没问题),然后尝试比较创建的工件并查看差异。 打开 environment.ts 文件,查看后端项目的基本 URL。 你在主类中使用@SpringBootApplication注解吗?您的主类应该扩展 SpringBootServletInitializer 并实现一个主类来实际启动 SpringApplication... 你可以试试马克所说的。另外,检查它是否在另一个版本的 Tomcat 中工作。 9 或 8。10 是仍处于 alpha 阶段的最新版本。 确保您的server.contextPath 配置正确,请参阅此***.com/questions/28089129/… 【参考方案1】:

项目中的配置正确。正如评论中提到的,Tomcat 10 可能存在一些问题,因为它在 alpha 版本中。我用过Tomcat 9,它工作正常。

配置如下。

第一步:pom.xml

中将打包选项改为war

&lt;packaging&gt;war&lt;/packaging&gt;

第 2 步: 扩展 SpringBootServletInitializer

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

/**
 * This is a helper Java class that provides an alternative to creating a @code web.xml.
 * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
 */
public class ApplicationWebXml extends SpringBootServletInitializer 

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)        
        return application.sources(ApplicationApp.class);
    

第 3 步: 创建 WAR 文件

mvn clean install 

我们开始了!我们可以访问端点

http://localhost:8080/context-path/endpoint OR
http://localhost:8080/war-filename/endpoint

我们还可以为war 创建配置文件,如下所示

<properties>
    <maven-war-plugin.version>3.2.3</maven-war-plugin.version>
</properties>

     <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>$maven-war-plugin.version</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>war</goal>
                            </goals>
                            <phase>package</phase>
                        </execution>
                    </executions>
                    <configuration>
                        <warSourceIncludes>WEB-INF/**,META-INF/**</warSourceIncludes>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                        <warSourceDirectory>target/classes/static/</warSourceDirectory>
                        <webResources>
                            <resource>
                                <directory>src/main/webapp</directory>
                                <includes>
                                    <include>WEB-INF/**</include>
                                </includes>
                            </resource>
                        </webResources>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>


    <profiles>
        <profile>
            <id>war</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>


【讨论】:

我也有类似的问题,不知道你能不能看看***.com/questions/69509053/…

以上是关于将 WAR 部署到 Tomcat(Spring Boot + Angular)的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot将WAR文件部署到Tomcat

spring boot 部署war 到tomcat上面静态资源无法访问

使用war将spring-boot和angular 7应用程序部署到tomcat 8.5中

spring boot项目打成war包部署到tomcat

将 Spring Boot WAR 部署到 Tomcat 8 - 访问资源时的 HTTP 404

SPRING BOOT 手动 War 文件部署到 Tomcat 并重新启动服务器,不创建数据库