将 Spring Boot WAR 部署到 Tomcat 8 - 访问资源时的 HTTP 404
Posted
技术标签:
【中文标题】将 Spring Boot WAR 部署到 Tomcat 8 - 访问资源时的 HTTP 404【英文标题】:Deploying Spring Boot WAR to Tomcat 8 - HTTP 404 when accessing resources 【发布时间】:2017-01-04 08:41:57 【问题描述】:我是 Spring Boot 的新手,正在努力将一个简单的 html Web 应用程序 (AngularJS) 部署到 Tomcat 8。这个 Web 应用程序只提供一些 HTML/CSS/JS 内容,没有对后端的 REST 调用。它已经使用 Webpack 进行了“编译”——这会生成 JS/CSS 包和一个 index.html 文件,该文件通过<script> / <link>
标签指向它们——并且已经在 ExpressJS 和带有嵌入式 tomcat 的 Spring Boot 上进行了测试,并且可以作为预期的。但是沿着独立 WAR 的路径并部署到 Tomcat 8 似乎无法正常工作。
对于 Spring Boot 项目,我已将所有 HTML/CSS/JS 文件包含在 src/main/resources/public
文件夹(无子文件夹)中,并且还配置了 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.my-app</groupId>
<artifactId>my-app</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>my-app</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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
“主”类:
package com.example.my.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
@SpringBootApplication
public class MyAppApplication extends SpringBootServletInitializer
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
return application.sources(MyAppApplication.class);
public static void main(String[] args)
SpringApplication.run(MyAppApplication.class, args);
以下是我用来进行 Tomcat 部署的步骤:
mvn clean package
生成 WAR
将 WAR 复制到路径/to/tomcat8/webapp
启动 Tomcat
http://localhost:8080/my-app => 自动加载 index.html
不幸的是,我看到的只是 404 错误,因为它找不到一些 JS/CSS 文件。有没有我遗漏的配置?
更新: 这是 index.html 文件(通过 Webpack 自动生成):
<!doctype html>
<html>
<head>
<base href="/">
<meta charset="utf-8">
<title>My App</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="icon" type="image/png" href="./assets/images/favicon.ico" />
<link href="/main-aa49893f83cc830596563d81f09a9611.css" rel="stylesheet"><link href="/main-5949f1f257a55a77e48bc4ab62fbc99a.css" rel="stylesheet"></head>
<body ng-app="myapp">
<ui-view></ui-view>
<script type="text/javascript" src="vendor-353ddb48f4ffe6546d59.js"></script><script type="text/javascript" src="app-353ddb48f4ffe6546d59.js"></script></body>
</html>
以下是我在访问 localhost:8080/my-app/index.html
时在 Chrome Web Inspector 中看到的错误:
http://localhost:8080/main-5949f1f257a55a77e48bc4ab62fbc99a.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/main-aa49893f83cc830596563d81f09a9611.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/vendor-4ba9083ed9802279c207.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/app-4ba9083ed9802279c207.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/vendor-4ba9083ed9802279c207.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/app-4ba9083ed9802279c207.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/main-aa49893f83cc830596563d81f09a9611.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/main-5949f1f257a55a77e48bc4ab62fbc99a.css Failed to load resource: the server responded with a status of 404 (Not Found)
还有一件事我忘了提。当我使用mvn clean package
生成战争时,src/main/resources/public 下的所有文件都放在WEB-INF/classes/resource
子文件夹中。根据研究,这些文件不是公开可见的(即,如果我尝试访问 localhost:8080/my-app/foo.css,它会给出 404)。这就是为什么 index.html 文件无法“看到”它所依赖的 JS/CSS 文件的原因吗?
【问题讨论】:
提供更多关于完整 404 错误是什么的上下文或包含您的 index.html 页面以便人们了解资源文件的加载方式会有所帮助。 【参考方案1】:嗯,我已经在我的 spring-boot
项目中尝试了其中的一些。
首先我要在我的项目pom.xml
添加一个依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
然后我会在src/main/resources/templates
上添加一个index.html
之后,您应该添加一个控制器以指向该索引
@Controller
public class AppController
@RequestMapping("/")
String index()
return "index";
有关详细信息,请参阅本指南。 Spring-boot and Thymeleaf
【讨论】:
这对原始问题没有任何帮助。您只是在展示如何使用模板引擎。最初的帖子说,只要将嵌入式 servlet 服务器放入外部服务器,他们就可以毫无问题地做到这一点。【参考方案2】:在没有更多上下文的情况下,您所描述的设置最常见的问题是您很可能使用绝对 URL 来指向您的 js / css 文件。因此,当您将它们放入 /my-app
下的 servlet 容器中时,它们不再正确引用,因为它们正试图转到根 /
。在描述资源文件在路径上的位置时,需要使用相对 URL。
【讨论】:
嗨,肖恩。我已经更新了答案。 index.html 文件包含指向资源的相对 URL。所有 HTML/CSS/JS 都在 src/main/resources/public 文件夹中,与 index.html 文件处于同一级别。【参考方案3】:我最终弄清楚了,但没有使用 Spring Boot 来打包 WAR 文件。在我的本地还有另一个项目,它使用普通的旧 Maven + pom.xml + web.xml
创建 WAR,我用它作为参考来找出当前项目无法正常工作的原因。存在多个问题:
http://localhost:8080/my-app
。 “编译的”AngularJS 应用程序的index.html
有一个<base href="/">
标记,需要指向/my-app/
而不是/
。这是 Web Inspector > Sources
中看不到 JS/CSS 文件的主要原因。
<link>
标签的 src
属性不应包含前导 /
对于我上面发布的 Spring Boot 应用程序,它带有一个嵌入式 Tomcat,并将应用程序部署在根上下文中,因此无需更改 index.html 文件中的任何路径。
与 Spring Boot 类似,我在 ExpressJS 中运行应用程序也没有问题,因为没有创建“子上下文”。同样,在这种情况下无需修改任何文件。
还有其他与查找资源(如 .ttf
文件)相关的错误,但至少应用能够运行。
更新:
看起来可以通过在server.xml
文件底部附近添加以下内容来从 Tomcat 8 根目录提供 WAR 文件:
<Context path="" docBase="my-app" debug="0" reloadable="true"></Context>
这将避免修改 index.html 文件的需要。
太棒了:)
【讨论】:
【参考方案4】:我遇到了同样的问题,它与 Webpack 的关系比与 Spring-boot 的关系更大。 在你的 webpack.common.js / webpack.prod.js 你必须设置:
metada.baseUrl = './';
并将其注入 index.html 中的 <base>
链接
而且你还必须设置
output.publicPath: './'
设置了两个变量,这对我有用。
【讨论】:
以上是关于将 Spring Boot WAR 部署到 Tomcat 8 - 访问资源时的 HTTP 404的主要内容,如果未能解决你的问题,请参考以下文章
一个 Spring Boot 项目,部署到 JAR 或 WAR
使用war将spring-boot和angular 7应用程序部署到tomcat 8.5中