首页 文章

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

提问于
浏览
67

我的 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 回答

  • 104

    将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错误的其他情况:

  • 1

    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

  • 0

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

    • 项目 - >属性

    • 点击“运行”

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

    enter image description here

相关问题