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

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

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

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

但这些都不起作用 . 他们都在Tomcat 6/7/8中继续返回如下所示的HTTP 404错误:

HTTP状态404 - / servlet描述:请求的资源(/ servlet)不可用 .

或者如下面的Tomcat 8.5 / 9:

HTTP状态404 - 未找到消息:/ servlet描述:源服务器未找到目标资源的当前表示或不愿意透露存在

为什么不起作用?

回答(3)

3 years ago

将servlet类放在包中

首先,将servlet类放在Java package 中 . 您应该始终将公开可重用的Java类放在一个包中,否则它们对于包中的类是不可见的,例如服务器本身 . 这样您就可以消除潜在的特定于环境的问题 . 无包装servlet仅适用于特定的Tomcat JDK组合,绝不应该依赖它 .

对于"plain" IDE项目,该类需要放在"Java Resources"文件夹内的包结构中,因此不需要"WebContent",这适用于JSP等Web文件 . 下面是Navigator视图中显示的默认Eclipse Dynamic Web Project的文件夹结构示例:

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

对于Maven项目,该类需要放在 main/java and thus not e.g. main/resources, this is for non-class files内的包结构中 . 下面是Eclipse的Navigator视图中显示的默认Maven webapp项目的文件夹结构示例:

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

请注意, /jsps 子文件夹不是严格必需的 . 你甚至可以不用它并将JSP文件直接放在webcontent / webapp root中,但我只是从你的问题中接过这个 .

在url-pattern中设置servlet URL

servlet URL指定为servlet映射的"URL pattern" . 绝对不是每个定义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 之类的路径参数,请使用 /servlet/* 的URL模式 . 另见Servlet and path parameters like /xyz//test, how to map in web.xml?

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

为了使用 @WebServlet ,您只需要确保 web.xml 文件(如果有的话)(自Servlet 3.0以来它是可选的)被声明为符合Servlet 3.0版本and thus not conform e.g. 2.5 version or lower . 下面是一个兼容Servlet 3.1(与Tomcat 8,WildFly 8,GlassFish 4等相匹配) .

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

或者,如果您尚未使用Servlet 3.0(不是Tomcat 7或更新版本,但Tomcat 6或更早版本),则删除 @WebServlet 注释 .

package com.example;

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

并在_758056中注册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类文件位于生成的WAR文件的 /WEB-INF/classes 文件夹中的包结构中 . 如果是 package com.example; public class YourServlet ,则必须位于 /WEB-INF/classes/com/example/YourServlet.class . 否则,如果 @WebServlet 也会出现404错误,或者 <servlet> 出现HTTP 500错误,如下所示:

HTTP状态500实例化servlet类com.example.YourServlet时出错

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

验证servlet是否正确编译并放置在类路径中的简单方法是让构建工具生成WAR文件(例如右键单击项目,Eclipse中的Export> WAR文件),然后使用ZIP工具检查其内容 . 如果 /WEB-INF/classes 中缺少servlet类,则项目配置错误或某些IDE /项目配置缺省值被错误地还原(例如,Eclipse中已禁用Project> Build Automatically) . 如果您不知道,最好从头开始重新启动,不要触摸任何IDE /项目配置默认值 .

单独测试servlet

如果服务器在 localhost:8080 上运行,并且WAR成功部署在 /contextname 的上下文路径上(默认为IDE项目名称,区分大小写!),并且servlet未初始化失败(读取任何服务器日志)部署/ servlet成功/失败消息以及实际的上下文路径和servlet映射),然后在 http://localhost:8080/contextname/servlet 处可以使用URL模式为 /servlet 的servlet .

您可以直接在浏览器的地址栏中输入它,以便对其进行测试 . 如果 doGet() 被正确覆盖并实现,那么您将在浏览器中看到它的输出 . 或者如果你没有 doGet() 或者如果它不正确地调用 super.doGet() ,那么,“HTTP 405: HTTP method GET is not supported by this URL”错误将显示(这仍然比404作为405的证据表明,该servlet本身实际上是找到) .

覆盖 service() 是一种不好的做法,除非你刚开始使用servlet并且对当前问题中描述的问题一无所知;)另见Design Patterns web based applications .

无论如何,如果在静态测试时servlet已经返回404,那么尝试使用HTML表单完全没有意义 . 从逻辑上讲,将任何HTML表单包含在来自servlet的404错误的问题中也是完全没有意义的 .

从HTML引用servlet URL

一旦您确认servlet在单独调用时工作正常,那么您可以前进到HTML . 至于HTML表单的具体问题, <form action> 值必须是有效的URL . 这同样适用于 <a href> . 您需要了解绝对/相对URL的工作原理 . 要知道,一个URL是,你可以输入网址/看到在网页浏览器's address bar. If you'重新指定相对URL的形式操作,即没有 http:// 方案,那么,你在你的网页浏览器's address bar. It'看看变成相对于当前网址因此绝对不会相对于服务器的WAR文件夹结构中的JSP / HTML文件位置,因为很多初学者似乎都在想 .

因此,假设与HTML表单的JSP页面被打开 http://localhost:8080/contextname/jsps/page.jsp ,你需要提交给位于 http://localhost:8080/contextname/servlet 一个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中使用直引号

您需要确保在 action="..."action='...' 等HTML属性中使用直引号,因此不能使用 action=”...”action=’...’ 等引号 . HTML中不支持卷曲引号,它们只会成为值的一部分 .

另见:

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

3 years ago

Scenario #1: 您从命令行 accidentially re-deployed ,而tomcat是 already running .

Short Answer: 停止Tomcat, delete target folder ,mvn包,然后重新部署


Scenario #2: request.getRequestDispatcher(“ MIS_SPELLED_FILE_NAME .jsp”)

Short Answer: 检查文件名 spelling ,确保 case 正确 .


Scenario #3: Class Not Found Exceptions (答案放在这里因为:问题#17982240)(java.lang.ClassNotFoundException for servlet in tomcat with eclipse)(被标记为重复并指示我在这里)

简短回答#3.1:web.xml在servlet-class标记中有错误的包路径 .

简短回答#3.2:java文件导入语句错误 .


以下是场景#1的更多详细信息:


1:停止Tomcat

  • 选项1:通过终端中的CTRL C .

  • 选项2 :(当tomcat仍在运行时终端关闭)

  • ------------ 2.1:按: Windows+R - >类型:“ services.msc

  • ------------ 2.2:在列表的名称列中查找"Apache Tomcat #.# Tomcat#" .

  • ------------ 2.3:右键单击 - >“ stop

2:删除"target"文件夹 . (mvn clean will not help you here)

3:mvn包

4:YOUR_DEPLOYMENT_COMMAND_HERE

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

Full Back Story:


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

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

部署失败后,我意识到我打开了两个git-bash窗口,并且 had not used CTLR+C to stop the previous deployment .

我遇到了:

HTTP状态404 - 未找到类型状态报告消息/if-student-test.jsp描述源服务器没有找到目标资源的当前表示,或者不愿意透露存在该目标资源 . Apache Tomcat / 8.5.31

以下是场景#3的更多详细信息:


SCENARIO 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:

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

例如:

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

你错误地写道:

package com.my_stuff

这很棘手,因为:

1:maven build(mvn包)不会在此报告任何错误 .

2:web.xml中的servlet-class行可以有CORRECT包路径 . 例如:

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

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

3 years ago

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

  • 项目 - >属性

  • 点击“运行”

  • 相对URL:/index.jsp(选择项目根URL)

enter image description here