May*_*air 5 html java tomcat http-status-code-404 embedded-tomcat-7
我一直试图通过Apache Tomcat
嵌入到应用程序中来使我的 Java 应用程序托管一个网页(一个 HTML 页面,而不是 JSP)。我使用Maven
了在构建系统NetBeans IDE 8.0.2.
出于某种原因,Tomcat
拒绝承认index.html
我已经放置在应用程序页面,尽管多次尝试和创建各种文件夹一样的WEB-INF
。但它仍然404
向我抛出错误。
这是我在我的项目中设置的一些相关代码(一些代码已被省略但与情况无关):
1. MainApplication.java - 启动 Tomcat
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.io.*;
import java.util.Optional;
import org.apache.catalina.startup.Tomcat;
public class MainApplication{
public static final Optional<String> port = Optional.ofNullable(System.getenv("PORT"));
public static void main(String[] args) throws Exception {
String contextPath = "/";
String appBase = ".";
Tomcat tomcat = new Tomcat();
tomcat.setPort(Integer.valueOf(port.orElse("8080")));
tomcat.getHost().setAppBase(appBase);
tomcat.addWebapp(contextPath, appBase);
tomcat.start();
tomcat.getServer().await();
}
}
Run Code Online (Sandbox Code Playgroud)
2. ShuttleServlet.java
@WebServlet(
name = "ShuttleServlet", urlPatterns = {"/shuttle"}
)
public class ShuttleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Code to interact with application to be added later
}
Run Code Online (Sandbox Code Playgroud)
3. 目录结构
- src
|
- main
|
- resources
- webapp
|
* index.html
* scripts.js
Run Code Online (Sandbox Code Playgroud)
4. Maven 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>TransportApp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<tomcat.version>7.0.57</tomcat.version>
</properties>
<build>
<finalName>TransportApp</finalName>
<resources>
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>TransportApp-${project.version}</finalName>
<archive>
<manifest>
<mainClass>com.example.TransportApp.MainApplication</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
5.Tomcat控制台日志
Dec 04, 2016 3:09:24 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Dec 04, 2016 3:09:24 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
Dec 04, 2016 3:09:24 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.57
Dec 04, 2016 3:09:24 AM org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
INFO: No global web.xml found
Dec 04, 2016 3:09:25 AM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [170] milliseconds.
Dec 04, 2016 3:09:25 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Run Code Online (Sandbox Code Playgroud)
404
尽管多次尝试和现在删除的文件夹,所有这些都会导致一个持久化。我希望所有这些都有助于找到罪魁祸首。
第一个 Maven 已经旧了,请使用 Gradle 代替;)
每个进程都有一个工作目录,当文件是相对的时,它将根据该目录进行解释。理解这一点很重要,因为除非您将其用于简单测试,否则开发和部署之间的目录结构可能不同。
如果你将程序构建为 jar 文件,像“./src/main/webapp”这样的相对 URL 很可能不起作用,因为“src/main”会消失,只留下“webapp”(就像当你构建一个WAR 文件)。
构建像 Gradle(和 Maven)这样的工具,并且您的 IDE 在编译后有一个“processResource”步骤,它将资源复制到(通常)成为类路径一部分的位置。由于除非您正在构建 Web 应用程序,否则不会复制 /main/resources/webapp,因此在 IDE 之外运行代码时将会遇到问题。
就我个人而言,我建议您构建一个 Spring boot 应用程序,该应用程序已经嵌入了 tomcat。在 Spring Boot 中,.html 文件是从类路径(main/resources/static)加载的,并且由于资源位于类路径内,因此它们在开发和部署中将具有相同的位置(因为资源处理)。
对于 Spring Boot Web 应用程序,您将需要一个依赖项 org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE 所以您的build.gradle文件将如下所示(您可以在 IDE 中创建一个 Gradle 项目)
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE")
}
Run Code Online (Sandbox Code Playgroud)
你的 Java Main 看起来像这样
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
将 .html 文件放入 /main/resources/static - 完成!正如您可能猜到的那样,Spring Boot 内部有很多魔力,而您不必编写更多代码的原因是因为 Spring Boot 团队选择了非常好的默认值,但如果您需要,请不要担心以后再进阶,这也是可能的。如果您需要服务器端渲染,您可以添加 org.springframework.boot:spring-boot-starter-thymeleaf:{version} ,并将模板放入 /resources/templates 中,然后就可以了。那里有很多很好的教程。
Spring 在 servlet 之上还有一个更好的抽象,称为控制器,同样有大量文档。