【问题标题】:Java+Maven+Embedded Tomcat: Project refuses to recognize web pageJava+Maven+Embedded Tomcat:项目拒绝识别网页
【发布时间】:2017-04-18 13:55:49
【问题描述】:

我一直在尝试通过嵌入应用程序的Apache Tomcat 使我的Java 应用程序托管一个网页(HTML 页面,而不是JSP)。我在NetBeans IDE 8.0.2. 上使用Maven 构建系统@ 出于某种原因,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();
    }
}

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
    } 

3.目录结构

- src
|
 - main
 |
  - resources
  - webapp
  |
    * index.html
    * scripts.js

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>

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"]

所有这些都导致404 尽管多次尝试和现在已删除的文件夹仍然存在。我希望所有这些都有助于找到罪魁祸首。

【问题讨论】:

    标签: java html tomcat http-status-code-404 embedded-tomcat-7


    【解决方案1】:

    问题的根本原因:

    问题在于您的 Launcher 类。在启动器类中,下面的代码行试图查看网络应用程序的同一目录,这本质上是不正确的。

     tomcat.addWebapp(contextPath, appBase);
    

    由于 appBase 设置为“.”,这意味着它将尝试查看您的启动器类所在的同一目录。

    解决方案

    尝试使用下面的代码,这很容易理解。您必须将 webApp 路径正确设置为 tomcat 上下文,以便在运行时点击该路径时识别它。

        String webappDirLocation = "src/main/webapp/";
        Tomcat tomcat = new Tomcat();
    
        //The port that we should run on can be set into an environment variable
        //Look for that variable and default to 8080 if it isn't there.
        String webPort = System.getenv("PORT");
        if(webPort == null || webPort.isEmpty()) {
            webPort = "8080";
        }
    
        tomcat.setPort(Integer.valueOf(webPort));
    
        StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
        System.out.println("configuring app with basedir: " + new File("./" + webappDirLocation).getAbsolutePath());
    
        // Declare an alternative location for your "WEB-INF/classes" dir
        // Servlet 3.0 annotation will work
        File additionWebInfClasses = new File("target/classes");
        WebResourceRoot resources = new StandardRoot(ctx);
        resources.addPreResources(new DirResourceSet(resources, "/WEB-     INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
        ctx.setResources(resources);
    
        tomcat.start();
        tomcat.getServer().await();
    

    【讨论】:

      【解决方案2】:

      第一个 maven 太旧了,改用 Gradle ;)

      每个进程都有一个工作目录,当一个文件是相对的时,它将被解释为与之相关的。 理解这一点很重要,因为除非您将其用于简单测试,否则开发和部署之间的目录结构可能会有所不同。

      如果您将程序构建为 jar 文件,则“./src/main/webapp”之类的相对 URL 很可能无法正常工作,因为“src/main”会消失,而只会留下“webapp”(当您构建一个 WAR 文件)。

      像 Gradle(和 Maven)这样的构建工具,您的 IDE 在编译后有一个“processResource”步骤,它将资源复制到(通常)将成为类路径的一部分的位置。由于 /main/resources/webapp 不会被复制,除非您正在构建 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")
      }
      

      你的 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);
          }
      }
      

      将 .html 文件放入 /main/resources/static - 完成! 正如你可能猜到的那样,Spring Boot 内部有很多神奇之处,而你不必再编写任何代码的原因是因为 Spring Boot 团队选择了非常好的默认值,但如果你需要也不要担心以后再进阶这也是可以的。如果您需要服务器端渲染,您可以添加 org.springframework.boot:spring-boot-starter-thymeleaf:{version},然后将您的模板放入 /resources/templates 中即可。那里有很多很好的教程。

      Spring 在称为控制器的 servlet 之上还有一个更好的抽象,同样有很多文档。

      【讨论】:

      • 当他问起一个独立的、嵌入 Tomcat 和 Maven 的问题时,你为什么要用一些 Gradle + Spring Boot 代码来回答?
      【解决方案3】:

      尝试使用 SpringBoot !!!它具有嵌入式tomcat, 使用 web 和 thymeleaf 依赖, thymeleaf 是可以识别您的网页的模板引擎。 尝试从这个网站http://start.spring.io/创建一个spring boot项目,这是一个spring初始化器,用于创建一个带有spring boot的maven项目。添加 web 和 thymeleaf 依赖并生成一个项目。 将您的 IDE 中的项目导入为 maven 项目, 或者使用 Spring 工具套装

      DemoApplication.java

       @Controller
       @SpringBootApplication
       public class DemoApplication {
           public static void main(String[] args) {
               SpringApplication.run(DemoApplication.class, args);
           }  
           @RequestMapping(value = "/homepage" , method = RequestMethod.GET  )
           public String sample()
           {
               return "home";
      
           }
      }
      

      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>jar</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.2.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.7</java.version>
      </properties>
      <dependencies>
           <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-thymeleaf</artifactId>
          </dependency>
          <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>
      </dependencies>
      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
          </build>
          </project>
      

      home.html

       <!DOCTYPE html>
       <html>
       <head>
       <meta charset="UTF-8"></meta>
       <title>HomePage</title>
       </head>
       <body>
       <h1>MY Spring Boot Home Page</h1>
       </body>
       </html>
      

      【讨论】:

      • 您显示 html 文件的解决方案是包含 3 个新库并重组整个应用程序?
      【解决方案4】:

      我认为您缺少主机名部分以及 maven 的构建步骤。尝试使用 maven 命令和 java -jar 命令运行。尝试以下查看是否有效。

       public static final Optional<String> PORT = Optional.ofNullable(System.getenv("PORT"));
      public static final Optional<String> HOSTNAME = Optional.ofNullable(System.getenv("HOSTNAME"));
      
      public static void main(String[] args) throws Exception {
          String contextPath = "/" ;
          String appBase = ".";
          Tomcat tomcat = new Tomcat();   
          tomcat.setPort(Integer.valueOf(PORT.orElse("8080") ));
          tomcat.setHostname(HOSTNAME.orElse("localhost"));
          tomcat.getHost().setAppBase(appBase);
          tomcat.addWebapp(contextPath, appBase);
          tomcat.start();
          tomcat.getServer().await();
      }
      

      按照以下步骤操作:(您需要在本地安装 maven) 打开cmd,转到源文件夹,pom文件所在的位置。执行以下命令

      mvn 编译

      然后按回车

      mvn 包。

      然后按回车

      cd 目标 然后回车

      java -jar [你的应用名称].jar(在目标文件夹中你会看到一个jar文件,把它的名字放在这里)

      从命令运行后,您将能够在浏览器中通过 localhost 进行浏览。 Netbeans run 给了我 404。我这样解决了。

      您可以查看此链接的运行 Web 应用程序部分: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/basic_app_embedded_tomcat/basic_app-tomcat-embedded.html

      【讨论】:

        【解决方案5】:

        我不知道你是否解决了这里描述的问题。 我希望这对其他人有帮助。 为了嵌入 Tomcat,我使用了插件而不是依赖项:因此,不需要主类和创建 tomcat 实例的代码。
        以下是 POM 必须包含的内容:

        <project ...>
          .....
          <dependencies>
            <!-- no need of any --->
          </dependencies>
          <build>
             <plugins>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.3</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>                    
                        <server>localhost</server>
                        <path>/${project.build.finalName}</path>
                    </configuration>
                </plugin>
        
            </plugins>
          </build>
        </project>
        

        这里是 web.xml 的示例

        <web-app id="WebApp_ID" version="2.4"
            xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
            http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        
        
           <display-name>My Test App</display-name>
           <description>A test app</description>
        
           <welcome-file-list>
              <welcome-file>index.html</welcome-file>
           </welcome-file-list>
        
           <session-config>
             <session-timeout>30</session-timeout>
           </session-config>
        </web-app>
        

        您既不需要主类也不需要内部代码(如问题所示)。 我们当然需要显示页面,所以这里是 index.html 的示例(如 web.xml 中所述):

        <html>
           <body>
              <h2>Hello World!</h2>
           </body>
        </html>
        

        在eclipse中:右键,以“run configuratuions”运行,在“Maven Build”下添加“New launch configuration”,设置Base目录,在“Goals”下输入:tomcat7:run。 而已! 你会得到:

        [INFO] Scanning for projects...
        [INFO]                                                                         
        [INFO] --------------------------------------------------------------------
        [INFO] Building rest-with-jersey Maven Webapp 0.0.1-SNAPSHOT
        [INFO] --------------------------------------------------------------------
        [INFO] 
        [INFO] >>> tomcat7-maven-plugin:2.2:run (default-cli) > process-classes @ rest-with-jersey >>>
        [INFO] 
        [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ rest-with-jersey ---
        [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
        [INFO] Copying 0 resource
        [INFO] 
        [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ rest-with-jersey ---
        [INFO] Nothing to compile - all classes are up to date
        [INFO] 
        [INFO] <<< tomcat7-maven-plugin:2.2:run (default-cli) < process-classes @ rest-with-jersey <<<
        [INFO] 
        [INFO] --- tomcat7-maven-plugin:2.2:run (default-cli) @ rest-with-jersey ---
        [INFO] Running war on http://localhost:8080/rest-with-jersey
        [INFO] Using existing Tomcat server configuration at /common/home/$$$/$$$$/lnx/workspace/rest-with-jersey/target/tomcat
        [INFO] create webapp with contextPath: /rest-with-jersey
        Sep 11, 2017 4:03:07 PM org.apache.coyote.AbstractProtocol init
        INFO: Initializing ProtocolHandler ["http-bio-8080"]
        Sep 11, 2017 4:03:07 PM org.apache.catalina.core.StandardService startInternal
        INFO: Starting service Tomcat
        Sep 11, 2017 4:03:07 PM org.apache.catalina.core.StandardEngine startInternal
        INFO: Starting Servlet Engine: Apache Tomcat/7.0.47
        Sep 11, 2017 4:03:09 PM org.apache.coyote.AbstractProtocol start
        INFO: Starting ProtocolHandler ["http-bio-8080"]
        
        In a browser with http://localhost:8080/rest-with-jersey/ you get the " Hello World!". 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-21
          • 2012-08-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-12
          相关资源
          最近更新 更多