Java Servlet返回";HTTP状态404请求的资源(/servlet)不可用;

Java Servlet返回";HTTP状态404请求的资源(/servlet)不可用;,java,forms,jsp,servlets,http-status-code-404,Java,Forms,Jsp,Servlets,Http Status Code 404,我的WebContent/jsps文件夹中的JSP文件中有一个HTML表单。我在src文件夹中的默认包中有一个servlet类servlet.java。在我的web.xml中,它被映射为/servlet 我在HTML表单的action属性中尝试了几个URL: 但这些都不管用。它们都不断返回HTTP 404错误,如Tomcat 6/7/8中的以下错误: HTTP状态404-/servlet 描述:请求的资源(/servlet)不可用 或如Tomcat 8.5/9中所述: HTTP状

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

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





但这些都不管用。它们都不断返回HTTP 404错误,如Tomcat 6/7/8中的以下错误:

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

或如Tomcat 8.5/9中所述:

HTTP状态404-未找到 消息:/servlet

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

为什么不起作用?

导言 这可能有很多原因,这些原因在以下章节中进行了分解:

  • 将servlet类放入
    包中
  • URL模式中设置servlet URL
  • @WebServlet
    仅适用于Servlet 3.0或更高版本
  • javax.servlet.*
    在servlet 5.0或更高版本中不再工作
  • 确保编译的
    *.class
    文件存在于内置WAR中
  • 在没有任何JSP/HTML页面的情况下单独测试servlet
  • 使用域相对URL从HTML引用servlet
  • 在HTML属性中使用直接引号
将servlet类放入
包中
首先,将servlet类放入Java
包中。您应该始终将可公开重用的Java类放在包中,否则它们对包中的类(例如服务器本身)是不可见的。这样可以消除潜在的特定于环境的问题。无包servlet只能在特定的Tomcat+JDK组合中工作,这是不应该依赖的

对于“普通”IDE项目,类需要放在其包结构中的“Java源代码”文件夹中,而不是放在“Web内容”文件夹中,该文件夹用于JSP等Web文件。下面是在Navigator视图中看到的默认Eclipse动态Web项目的文件夹结构示例(“Java源代码”文件夹默认位于该项目中,由
src
文件夹表示):

EclipseProjectName
|--src
|`--com
|`--例如
|`--YourServlet.java
|--网络内容
||--WEB-INF
||`--web.xml
|`--JSP
|`--page.jsp
:
在Maven项目中,类需要放在
main/java
中的包结构中,因此不是
main/resources
,也绝对不是
main/webapp
,这是用于web文件的。下面是在Eclipse的Navigator视图中看到的默认Maven webapp项目的文件夹结构示例:

MavenProjectName
|--src
|`--主要
||--java
||`--com
||`--示例
||`--YourServlet.java
||——资源
|`--webapp
||--WEB-INF
||`--web.xml
|`--JSP
|`--page.jsp
:
请注意,
/jsps
子文件夹并非绝对必要。您甚至可以不使用它,直接将JSP文件放在webcontent/webapp根目录中,但我只是从您的问题中接过这个问题

URL模式中设置servlet URL
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.
    // ...
}
package com.example;

public class YourServlet extends HttpServlet {
    // ...
}
如果您希望支持路径参数,如
/servlet/foo/bar
,则使用URL模式
/servlet/*
。另见

@WebServlet
仅适用于Servlet 3.0或更高版本 为了使用
@WebServlet
,您只需要确保您的
web.xml
文件(如果有)(自Servlet 3.0以来是可选的)声明为符合Servlet 3.0+版本。下面是一个与Servlet 4.0兼容的版本(与Tomcat 9+、WildFly 11+、Payara 5+等匹配)

并在
web.xml
中注册servlet,如下所示:


yourServlet
com.example.YourServlet
yourServlet
/servlet
因此请注意,您不应同时使用这两种方法。使用基于注释的配置或基于XML的配置。如果两者都有,则基于XML的配置将覆盖基于注释的配置

javax.servlet.*
在servlet 5.0或更高版本中不再工作 自雅加达EE 9/Servlet 5.0(Tomcat 10、TomEE 9、WildFly 22预览版、GlassFish 6、Payara 6、Liberty 22等)以来,
javax.
包已重命名为
Jakarta.

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

import javax.servlet.*;
导入javax.servlet.http.*;

import jakarta.servlet.*;
导入jakarta.servlet.http.*;
如果您使用的是Maven,您可以在下面的答案中找到Tomcat 10+、Tomcat 9-、JEE 9+和JEE 8的正确
pom.xml
声明示例:

确保编译的
*.class
文件存在于内置WAR中 如果您使用的是Eclipse和/或Maven等构建工具,那么您需要绝对确保编译后的servlet类文件位于生成的WAR文件的
/WEB-INF/classes
文件夹中的包结构中。如果是
包com.ex
package com.example;

public class YourServlet extends HttpServlet {
    // ...
}
   package my_stuff;
   <servlet-class>
   my_stuff.MyClass
   </servlet-class>
package com.my_stuff
<servlet-class>
my_stuff.MyClass
</servlet-class>
var button = document.getElementById("<<button-id>>");
button.addEventListener("click", function() {
  window.location.href= "<<full-servlet-path>>" (eg. http://localhost:8086/xyz/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>
//@WebServlet("/FirstServ")
//@WebServlet("/SecondServ")
<servlet>
        <servlet-name>ControllerA</servlet-name>
        <servlet-class>PackageName.ControllerA</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>ControllerA</servlet-name>
        <url-pattern>/theController</url-pattern>
</servlet-mapping>
<form action="theController" method="POST">
</form>
<?xml version="1.0" encoding="UTF-8"?>

<element>

<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_3_1.xsd"
         version="3.1">
     
<servlet> 
    <servlet-name>InsertServlet</servlet-name> 
    <servlet-class>com.worklog.InsertServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>InsertServlet</servlet-name> 
    <url-pattern>/insert</url-pattern> 
</servlet-mapping>

</web-app>

</element>