当前位置: 首页 > 知识库问答 >
问题:

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

张宣
2023-03-14

我的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">
html prettyprint-override"><form action="../servlet.java">

但这些都没用。它们都在Tomcat 6/7/8中不断返回HTTP 404错误,如下所示:

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

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

消息:/servlet

描述:源服务器找不到目标资源的当前表示形式,或者不愿意公开存在的表示形式

为什么不起作用?

共有2个答案

子车煌
2023-03-14

场景#1:当tomcat已经运行时,您意外地从命令行重新部署。

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

场景2:Request.GetRequestDispatcher(“mis_spelled_file_name.jsp”)

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

场景#3:类找不到异常(答案放在这里是因为:问题#17982240)(java.lang.ClassNotFoundException用于带有eclipse的tomcat中的servlet)(被标记为duplicate并指示我到这里)

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

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

1:停止Tomcat

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

2:删除“目标”文件夹。(mvn清洁在这里不会帮到你)

3:mvn包

4:YOUR_DEPLOYMENT_COMMAND_HERE

(我的:Java-jar target/dependency/webapp-runner.jar--端口5190 target/*.war)

完整的背景故事:

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

Java-jar target/dependency/webapp-runner.jar--端口5190 target/*.war

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

会见我的是:

HTTP状态404-找不到类型状态报表

消息/if-student-test.jsp

说明源服务器找不到目标资源的当前表示形式,或者不愿意透露存在此表示形式。

Apache Tomcat/8.5.31

场景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>

使用的堆栈:记事本+++GitBash+Maven+Heroku Web App Runner+Tomcat9+Windows10:

阎劲
2023-03-14

这可能有很多原因,下面各节对其进行了细分:

  • 将servlet类放入
  • url-pattern
  • 中设置servlet URL
  • @webservlet仅适用于Servlet 3.0或更新版本
  • javax.Servlet.*在Servlet 5.0或更新版本中不再工作
  • 确保编译的*.class文件存在于生成的WAR中
  • 在没有任何JSP/HTML页面的情况下单独测试servlet
  • 使用域相关URL从HTML引用servlet
  • 在HTML属性中使用直引号

首先,将servlet类放在一个Java中。您应该始终将可公开重用的Java类放在一个包中,否则它们对于包中的类是不可见的,例如服务器本身。这样就消除了潜在的特定于环境的问题。无包servlet只能在特定的Tomcat+JDK组合中工作,这一点永远不应该依赖。

如果是“普通”IDE项目,则类需要放在“Java资源”文件夹中的包结构中,而不是“WebContent”,这是针对诸如JSP之类的web文件。下面是在Navigator视图中看到的默认Eclipse Dynamic Web项目的文件夹结构示例:

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

对于Maven项目,类需要放在main/的包结构中,而不是main/resources中,这是用于非类文件的,绝对也不是main/webapp,这是用于web文件的。下面是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中,但我只是从您的问题中接手这个问题。

servlet URL被指定为servlet映射的“URL模式”。按照定义,它绝对不是servlet类的classname/filename。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和路径参数,如/xyz/{value}/test,如何在web.xml中映射?

为了使用@webservlet,您只需要确保您的web.xml文件(如果有的话)(从Servlet3.0开始,它是可选的)被声明为符合Servlet3.0+版本,因此不符合例如2.5版本或更低版本。下面是Servlet4.0兼容的一个(与Tomcat9+、WildFly11+、Payara5+等匹配)。

<?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>

或者,如果您还没有使用Servlet3.0+(例如,Tomcat6或更高版本),那么可以删除@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的配置将覆盖基于注释的配置。

自从Jakarta EE 9/Servlet 5.0(Tomcat 10、TomEE 9、WildFly 22预览、GlassFish 6、Payara 6、Liberty 22等)以来,javax.*包已被重命名为Jakarta.*包。

换句话说,请绝对确保不要仅仅为了让javax.*编译而在WAR项目(如tomcat-servlet-api-9.x.x.JAR)中随机放置不同服务器的JAR文件。这只会惹来麻烦。将其完全删除并编辑servlet类的导入

import javax.servlet.*;
import javax.servlet.http.*;

import jakarta.servlet.*;
import jakarta.servlet.http.*;

如果您使用的是Maven,您可以在下面的答案中找到Tomcat10+、Tomcat9-、Jee9+和Jee8-的正确pom.xml声明的示例:Tomcat9将servlet转换为javax.servlet.servlet,而不是jakarta.servlet.http.HttpServlet

如果您使用的是构建工具,如Eclipse和/或Maven,那么您需要绝对确保编译后的servlet类文件驻留在生成的WAR文件的/WEB-INF/文件夹中的包结构中。在包com.example的情况下;公共类yourservlet,它必须位于/web-inf//com/example/yourservlet.class中。否则,在@webservlet的情况下,您将面临404错误,或者在 的情况下,您将面临HTTP 500错误,如下所示:

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

并在服务器日志中找到一个java.lang.ClassNotFoundException:com.example.YourServlet,后面是一个java.lang.NoClassDeffounder:com.example.YourServlet,然后是javax.servlet.ServletException:实例化servlet类com.example.YourServlet

验证servlet是否被正确编译并放置在类路径中的一个简单方法是让构建工具生成一个WAR文件(例如,右键单击project,Export>WAR file in Eclipse),然后使用ZIP工具检查其内容。如果/web-inf/中缺少servlet类,或者导出导致错误,则说明项目配置错误,或者某些IDE/项目配置默认值被错误还原(例如,在Eclipse中禁用了project>Build Automatically)。

您还需要确保项目图标没有指示生成错误的红叉。您可以在Problems视图(窗口>显示视图>其他...)中找到确切的错误。通常情况下,错误消息是可以搜索的。如果您没有头绪,最好是从头重新启动,不要触及任何IDE/项目配置默认值。如果您正在使用Eclipse,您可以找到如何在Eclipse项目中导入javax.servlet API的说明?

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

您可以直接在浏览器的地址栏中输入它来进行测试。如果它的doget()被正确重写和实现,那么您将在浏览器中看到它的输出。或者如果您没有任何doget()或者如果它错误地调用了super.doget(),那么将显示一个“HTTP 405:此URL不支持HTTP方法GET”错误(这仍然比404好,因为405是实际找到servlet本身的证据)。

重写service()是一种糟糕的做法,除非您正在重新创建一个MVC框架--如果您刚刚开始使用Servlet,并且对当前问题中描述的问题一无所知,那么这是很不可能的;)另请参阅Design Patterns web based Applications。

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

一旦您验证了servlet在单独调用时运行良好,那么您就可以进入HTML了。至于HTML表单的具体问题,

值需要是一个有效的URL。这同样适用于 。您需要了解绝对/相对URL是如何工作的。您知道,URL是您可以在WebBrowser的地址栏中输入/查看的web地址。如果您指定一个相对URL作为表单操作,即没有 http://方案,那么它就会变成相对于您在WebBrowser地址栏中看到的当前URL。因此,它与服务器的WAR文件夹结构中的JSP/HTML文件位置绝对不相关,正如许多初学者所想的那样。

因此,假设带有HTML表单的JSP页面是由http://localhost:8080/contextname/jsps/page.JSP打开的(因此不是由file:/...),并且您需要提交到http://localhost:8080/contextname/servlet中的servlet,下面有几种情况(注意,您可以在这里安全地用替换):

>

  • 表单操作提交给带有前导斜杠的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=“...”,而不是卷引号,如action=“...”action=“...”。HTML中不支持卷引号,它们只是成为值的一部分。当从博客复制粘贴代码段时要小心!一些博客引擎,特别是Wordpress,默认使用所谓的“智能引号”,这样也会破坏代码片段中的引号。另一方面,不是复制粘贴代码,而是尝试自己简单地键入代码。通过你的大脑和手指实际获取代码的另外一个好处是,它将使你更好地记住和理解代码,并使你成为一个更好的开发人员。

  •  类似资料:
    • 我的文件夹中的JSP文件中有一个HTML表单。我有一个servlet类在文件夹中的默认包中。在我的它被映射为。 我在HTML表单的属性中尝试了几个URL: 但这些都不管用。它们都会不断返回HTTP 404错误,如Tomcat 6/7/8中的以下错误: 描述:请求的资源(/servlet)不可用。 或如Tomcat 8.5/9中所示: 消息:/servlet 描述:源服务器没有找到目标资源的当前表示

    • 我正在制作一个简单的程序,以几个字段作为输入,然后点击确认按钮后,confirm.jsp将出现。 我创建了Controller.java servlet来标识单击的按钮,然后打开JSP。controller.java存储在web-inf/classes/ch2/servletController目录中,而submit.jsp、register.jsp、confirm.jsp存储在/ch2/serv

    • 我在使用MyEclipse IDE中的Tomcat服务器和Struts 2框架时遇到了一个反复出现的问题。我正在运行我的程序作为一个服务器应用程序,当它运行时,默认的index.jsp文件将成功打开,但该应用程序的其他过去都将无法工作。当试图加载任何我的。do页面,我得到以下错误:HTTP状态404:请求的资源....不可用。当我以前遇到这个错误时,我只是重启了服务器,一切都很好,但是我现在没有同

    • 当我开始login.jsp表单并键入用户名和密码时,我有这个错误错误错误是HTTP状态404:请求的资源不可用。 我错过了什么?有什么帮助吗? 登录。JAVA 登录。jsp Web.xml Struts配置 这就是我http://www.tutorialspoint.com/struts_2/struts_database_access.htm

    • 问题内容: 在Tomcat服务器上运行Eclipse项目时出现以下错误: HTTP状态404-请求的资源(/ ProjectName /)不可用。 浏览器地址栏中的URL为。 我真的不知道文件中缺少什么。我在文件夹中有一个,并且我的包含以下条目: 问题答案: 默认情况下,当您打开项目根文件夹而不是中的物理文件时,服务器将在中查找欢迎文件。如果未找到任何内容,则将出现此404“找不到页面”错误。 就

    • 问题是:我的index.jsp和web.xml总是进入HTTP404和500 我用的是Tomcat6。 这来自index.jsp: 当我注册时: 我点击名字和姓氏,进入404,信息是: 类型状态报告 根据请求,下面是 这里还有项目树: