Servlet返回“ HTTP状态404请求的资源(/ Servlet)不可用”


94

我的文件WebContent/jsps夹中的JSP文件中有HTML表单。servlet.java我的默认包中的src文件夹中有一个servlet类。在我中,web.xml它映射为/servlet

action在HTML表单的属性中尝试了几个URL :

<form action="/servlet">
<form action="/servlet.java">
<form action="/src/servlet.java">
<form action="../servlet.java">

但是这些都不起作用。他们都不断返回HTTP 404错误,例如在Tomcat 6/7/8中:

HTTP状态404-/ servlet

描述:请求的资源(/ servlet)不可用。

或在Tomcat 8.5 / 9中如下所示:

HTTP状态404 —找不到

消息:/ servlet

描述:原始服务器未找到目标资源的当前表示,或不愿意透露存在的一种表示形式

为什么不起作用?

Answers:


127

将Servlet类放入 package

首先,将servlet类放入Java中package。你应该总是将可公共重用的Java类放在包中,否则它们对于包中的类(例如服务器本身)是不可见的。这样,您就可以消除潜在的特定于环境的问题。无软件包servlet仅在特定的Tomcat + JDK组合中工作,并且永远不应依赖于此。

如果是“普通” IDE项目,则需要将该类放在其包结构中的“ Java Resources”文件夹中,而不是 “ WebContent”中,这是针对Web文件(如JSP)的。下面是在导航器视图中看到的默认Eclipse Dynamic Web Project文件夹结构的示例:

EclipseProjectName
 |-- src
 |    `-- com
 |         `-- example
 |              `-- YourServlet.java
 |-- WebContent
 |    |-- WEB-INF
 |    |    `-- web.xml
 |    `-- jsps
 |         `-- page.jsp
 :

在一个Maven项目的情况下,类需要被放置在其封装结构内main/java 并因此例如main/resources,这是对于非类文件。下面是一个默认的Maven webapp项目的文件夹结构示例,如Eclipse的Navigator视图所示:

MavenProjectName
 |-- src
 |    `-- main
 |         |-- java
 |         |    `-- com
 |         |         `-- example
 |         |              `-- YourServlet.java
 |         |-- resources
 |         `-- webapp
 |              |-- WEB-INF
 |              |    `-- web.xml
 |              `-- jsps
 |                   `-- page.jsp
 :

请注意,该/jsps子文件夹不是严格必需的。您甚至可以不使用它,而将JSP文件直接放在webcontent / webapp根目录中,但是我只是从您的问题中接管该文件。

在中设置servlet URL url-pattern

servlet URL被指定为servlet映射的“ URL模式”。根据定义,它绝对不是servlet类的类名/文件名。URL模式将被指定为@WebServlet注释值。

package com.example; // Use a package!

@WebServlet("/servlet") // This is the URL of the servlet.
public class YourServlet extends HttpServlet { // Must be public and extend HttpServlet.
    // ...
}

如果您想支持路径参数(例如)/servlet/foo/bar,请改用URL模式/servlet/*。另请参阅Servlet和路径参数,例如/ xyz / {value} / test,如何在web.xml中进行映射?

@WebServlet 仅适用于Servlet 3.0或更高版本

为了使用@WebServlet,您只需要确保您的web.xml文件(如果有的话(从Servlet 3.0起是可选的))声明为符合Servlet 3.0+版本,因此符合2.5版或更低版本。下面是与Servlet 4.0兼容的一个(与Tomcat 9 +,WildFly 11 +,Payara 5+等匹配)。

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0"
>
    <!-- Config here. -->
</web-app>

或者,如果您尚未使用Servlet 3.0+(例如Tomcat 6或更早版本),请删除@WebServlet注释。

package com.example;

public class YourServlet extends HttpServlet {
    // ...
}

web.xml像这样注册servlet :

<servlet>
    <servlet-name>yourServlet</servlet-name>
    <servlet-class>com.example.YourServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>yourServlet</servlet-name>
    <url-pattern>/servlet</url-pattern>  <!-- This is the URL of the servlet. -->
</servlet-mapping>

因此请注意,您不应同时使用两种方式。使用基于注释的配置或基于XML的配置。两者兼有时,基于XML的配置将覆盖基于注释的配置。

验证构建/部署

如果您正在使用诸如Eclipse和/或Maven之类的构建工具,则需要绝对确保已编译的Servlet类文件位于其/WEB-INF/classes生成的WAR文件的文件夹中的包结构中。如果是这样package com.example; public class YourServlet,它必须位于中/WEB-INF/classes/com/example/YourServlet.class。否则,您也将面临@WebServlet404错误或<servlet>HTTP 500错误的情况,如下所示:

HTTP状态500

实例化servlet类com.example.YourServlet时出错

并在服务器日志中找到a java.lang.ClassNotFoundException: com.example.YourServlet,然后是a java.lang.NoClassDefFoundError: com.example.YourServlet,依次是javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet

验证servlet是否正确编译并放置在classpath中的一种简单方法是让构建工具生成WAR文件(例如,右键单击项目,在Eclipse中为Export> WAR文件),然后使用ZIP工具检查其内容。如果缺少servlet类/WEB-INF/classes,或者如果导出导致错误,则说明该项目配置错误或某些IDE /项目配置默认值被错误地还原(例如,在Eclipse中已禁用“ 项目”>“自动生成”)。

您还需要确保项目图标上没有红叉指示构建错误。您可以在“ 问题” 视图(“ 窗口”>“显示视图”>“其他...”)中找到确切的错误。通常错误消息是可以正常使用的。如果您没有任何线索,最好是从头开始,并且不要触摸任何IDE /项目配置默认值。如果您使用的是Eclipse,则可以在如何在Eclipse项目中导入javax.servlet API中找到说明

分别测试servlet

假设服务器在上运行localhost:8080,并且WAR成功部署在上下文路径/contextname(默认为IDE项目名称,区分大小写!)上,并且Servlet初始化未失败(读取服务器日志以获取任何deploy / servlet成功/失败消息以及实际的上下文路径和servlet映射),则网址为的servlet /servlet可以在http://localhost:8080/contextname/servlet

您可以直接在浏览器的地址栏中输入它,以进行个性化测试。如果doGet()正确覆盖并实现了它,那么您将在浏览器中看到其输出。或者,如果您没有任何内容doGet()或调用不正确super.doGet(),则此URL不支持HTTP 405:HTTP方法GET ”错误(与404相比,它比404更好,因为它表明Servlet是405本身被发现)。

service()除非您重新发明了MVC框架,否则重写是一个坏习惯,除非您刚开始使用servlet并且对于当前问题中描述的问题一无所知,否则覆盖是非常不可能的;)另请参见基于Web的设计模式应用程序

无论如何,如果该servlet在进行不定期测试时已经返回404,那么尝试使用HTML表单是完全没有意义的。从逻辑上讲,因此在有关Servlet的404错误的问题中包含任何HTML表单也是毫无意义的。

从HTML引用servlet URL

一旦确认servlet单独调用时可以正常工作,就可以使用HTML。至于HTML表单的具体问题,该<form action>值必须是有效的URL。同样适用于<a href>。您需要了解绝对/相对URL的工作方式。您知道,URL是一个网址,您可以在浏览器的地址栏中输入/查看。如果您要指定一个相对URL作为表单操作,即没有http://方案,那么它将变成相对于当前 URL的相对,如您在Web浏览器的地址栏中看到的那样。因此,它绝对不像许多初学者认为的那样相对于服务器的WAR文件夹结构中的JSP / HTML文件位置。

因此,假设与HTML表单的JSP页面被打开http://localhost:8080/contextname/jsps/page.jsp,你需要提交给位于一个servlet http://localhost:8080/contextname/servlet,下面是一些例子(注意,你可以放心地替代<form action><a href>这里):

  • 表单操作会以斜杠提交到URL。

    <form action="/servlet">

    前导斜杠/使URL相对于域,因此表单将提交给

    http://localhost:8080/servlet

    但这可能会导致404,因为它处于错误的上下文中。


  • 表单操作提交到URL时不带斜杠。

    <form action="servlet">

    这使得URL相对于当前URL的当前文件夹,因此该表单将提交到

    http://localhost:8080/contextname/jsps/servlet

    但这可能会导致404,因为它位于错误的文件夹中。


  • 表单操作将提交到向上一个文件夹的URL。

    <form action="../servlet">

    这将向上一个文件夹(就像在本地磁盘文件系统路径中一样!),因此表单将提交到

    http://localhost:8080/contextname/servlet

    这个必须工作!


  • 但是,规范的方法是使URL相对于域,这样,当您碰巧将JSP文件移动到另一个文件夹时,就无需再次修复URL。

    <form action="${pageContext.request.contextPath}/servlet">

    这将产生

    <form action="/contextname/servlet">

    因此,它将始终提交到正确的URL。


在HTML中使用直引号

你需要绝对确保你使用的直引号在HTML属性,如action="..."action='...'因而不能像弯引号action=”...”action=’...’。HTML不支持使用弯引号,它们只是成为值的一部分。

也可以看看:

HTTP状态404错误的其他情况:


1
使用glassfish的web-app version =“ 3.1”,当我在web.xml和批注中进行映射时,就可以单独测试servlet了。由于我具有最新版本,因此我删除了映射并留下了注释,但是我会收到404错误?
SallyRothroat

1
如果您将servlet 2.5或更早版本的库包含在webapp本身中,而不是依靠目标运行时本身来提供servlet库,则会发生这种情况。
BalusC '18

@xdola:确实很脆弱,因为它取决于请求URI。只需阅读答案即可获得有关您的问题以及正确方法的解释。
BalusC

4

场景1:您在tomcat 已经运行不小心从命令行重新部署了。

简短答案:停止Tomcat,删除目标文件夹,mvn软件包,然后重新部署


方案2: request.getRequestDispatcher(“ MIS_SPELLED_FILE_NAME .jsp”)

简短答案:检查文件名的拼写,确保大小写正确。


场景3:未找到类异常 (答案在这里,因为:问题#17982240)(带有eclipse的tomcat中的servlet的java.lang.ClassNotFoundException)(被标记为重复,并在此处定向了我)

简短答案#3.1:web.xml在servlet类标签中的包路径错误。

简短答案#3.2:Java文件导入错误的语句。


以下是方案1的更多详细信息:


1:停止Tomcat

  • 选项1:通过终端中的CTRL + C。
  • 选项2 :(在Tomcat仍运行时终端关闭)
  • ------------ 2.1:按下:Windows + R- >键入:“ services.msc
  • ------------ 2.2:在列表的“名称”列中找到“ Apache Tomcat#。#Tomcat#”。
  • ------------ 2.3:右键单击->“ 停止

2:删除“目标”文件夹。 (mvn clean不会在这里帮助您)

3:MVN包

4:YOUR_DEPLOYMENT_COMMAND_HERE

(我的:java -jar target / dependency / webapp-runner.jar --port 5190 target / *。war)

完整故事:


意外地打开了一个新的git-bash窗口,并尝试通过以下方式为我的heroku项目部署.war文件:

java -jar target / dependency / webapp-runner.jar --port 5190 target / *。war

部署失败后,我意识到我打开了两个git-bash窗口,并且没有使用CTLR + C停止先前的部署

我遇到了:

HTTP状态404 –找不到类型状态报告

消息/if-student-test.jsp

描述原始服务器找不到目标资源的当前表示,或者不愿意透露该资源的存在。

Apache Tomcat / 8.5.31

以下是方案3的更多详细信息:


场景3.1:您的web.xml文件中的servlet类包路径错误。

它应该匹配Java Servlet类顶部的package语句。

文件:my_stuff / MyClass.java

   package my_stuff;

文件:PRJ_ROOT / src / main / webapp / WEB-INF / web.xml

   <servlet-class>
   my_stuff.MyClass
   </servlet-class>

场景3.2:

您在myClass.java文件的顶部放置了错误的“ package ”语句。

例如:

文件位于:“ / my_stuff ”文件夹中

您错误地写道:

package com.my_stuff

这很棘手,因为:

1:maven版本(mvn软件包)在这里不会报告任何错误。

2:web.xml中的servlet类行可以具有正确的包路径。例如:

<servlet-class>
my_stuff.MyClass
</servlet-class>

使用的堆栈: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10


您的AppName.war以及因此爆炸的文件夹名称与您的预期名称不匹配,例如,当您的war文件版本为AppName-1.0-SNAPSHOT.war时,而您正在尝试/ AppName /。
jla

0

HTTP Status 404在NetBeans IDE中的解决方案:右键单击您的项目,然后转到您的项目属性,然后单击“运行”,然后输入您的项目相对URL,例如index.jsp

  1. 项目->属性
  2. 点击运行
  3. 相对URL:/index.jsp(选择项目根URL)

在此处输入图片说明


0

我的问题是我的方法缺少@RequestBody批注。添加注释后,我不再收到404异常。


0

请执行以下两个步骤。我希望它将解决在Java Servlet应用程序开发过程中tomcat服务器中的“ 404 not found”问题。

第1步: Right click on the server(in the server explorer tab)->Properties->Switch Location from workspace metadata to tomcat server

第2步: Double Click on the server(in the server explorer tab)->Select Use tomcat installation option inside server location menu


0

我删除了旧的Web库,例如spring框架库。并建立图书馆的新路径。然后就可以了。


0

一个旧线程,但是由于我没有在其他地方找到它,因此还有另一种可能性:

如果您使用的servlet-API 3.0+,那么你的web.xml文件必须包括metadata-complete="true"属性

在此处输入图片说明

这告诉tomcat使用给定的数据web.xml而不是使用@WebServlet注释来映射servlet 。



0

对我有用的解决方法是(如果使用的是Maven):右键单击您的项目,Maven->更新项目。这可能会给您JDK和其他库(在我的情况下是MySQL连接器)带来其他错误,但是一旦修复它们,您的原始问题就应该得到解决!


0

如果您想在不使用“表单”和“提交”按钮的情况下使用javascript打开Servlet,则以下代码如下:

var button = document.getElementById("<<button-id>>");
button.addEventListener("click", function() {
  window.location.href= "<<full-servlet-path>>" (eg. http://localhost:8086/xyz/servlet)
});

键:

1)button-id:您在html / jsp文件中为按钮赋予的'id'标签。

2)full-servlet-path:单独运行servlet时在浏览器中显示的路径


0

我已经在web.xml中进行了映射:-

  1. 如果为新程序制作了另一个软件包,那么我们必须提到:-

在xml文件中的servlet类标签的打开和关闭之间的packagename.filename。

  1. 如果您正在xml中映射文件,但它们不起作用或显示错误,请在相应文件中的代码注释行上进行注释。

两种方法无法相互配合使用,因此我要么使用创建servlet时提到的文件的注释方法,要么使用映射方式,然后删除或注释注释行。例如:

 <servlet>
   <servlet-name>s1</servlet-name>
   <servlet-class>performance.FirstServ</servlet-class>
   </servlet>    
   
   <servlet-mapping>
   <servlet-name>s1</servlet-name>
   <url-pattern>/FirstServ</url-pattern>
   </servlet-mapping>
   
   <servlet>
   <servlet-name>s2</servlet-name>
   <servlet-class>performance.SecondServ</servlet-class>
   </servlet>
   
   <servlet-mapping>
   <servlet-name>s2</servlet-name>
   <url-pattern>/SecondServ</url-pattern>
   </servlet-mapping>

如果已完成xml中的映射,则注释相应文件中的代码注释行。

//@WebServlet("/FirstServ")
//@WebServlet("/SecondServ")

-1

请检查上下文根不能为空

如果您使用的是eclipse:
右键单击,选择属性,然后选择Web项目设置。检查上下文根不能为空

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.