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 – 未find
消息 :/ servlet
说明 :原始服务器没有find目标资源的当前表示,或者不愿意透露目标资源的存在
为什么它不工作?
把servlet类放在一个package
首先,把这个servlet类放在一个Java package
。 您应该始终在一个包中公开可重用的Java类,否则它们对于包中的类(如服务器本身)是不可见的。 这样可以消除潜在的环境特定问题。 无包servlet只能在特定的Tomcat + JDK组合中工作,不应该依赖这个组合。
对于“普通”IDE项目,该类需要放在“Java Resources”文件夹内的包结构中,因此不是 “WebContent”,这是针对诸如JSP的Web文件。 以下是导航器视图中所示的默认Eclipse dynamicWeb项目的文件夹结构示例:
EclipseProjectName |-- src | `-- com | `-- example | `-- YourServlet.java |-- WebContent | |-- WEB-INF | | `-- web.xml | `-- jsps | `-- page.jsp :
在Maven项目的情况下,这个类需要被放在main/java
里面的包结构中,因此不需要 main/resources
,这个是非类文件 。 以下是在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的根,但我只是接pipe你的问题。
以url-pattern
设置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. // ... }
如果您想要支持像/servlet/foo/bar
这样的path参数,请使用/servlet/*
的URL模式。 另请参阅像/ xyz / {value} / test这样的Servlet和path参数,如何在web.xml中映射?
@WebServlet
仅适用于Servlet 3.0或更新版本
为了使用@WebServlet
,你只需要确保你的web.xml
文件(如果有的话)(Servlet 3.0以后是可选的)被声明为符合Servlet 3.0+版本,因此不符合2.5版本或更低的版本 。 下面是一个与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 { // ... }
然后把servlet注册到web.xml
如下所示:
<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>
请注意,你不应该使用两种方式。 使用基于注释的configuration或基于XML的configuration。 如果两者都有,那么基于XML的configuration将覆盖基于注释的configuration。
validation构build/部署
如果您使用的是Eclipse和/或Maven等构build工具,则需要确保编译的servlet类文件位于生成的WAR文件的/WEB-INF/classes
文件夹中的包结构中。 在package com.example; public class YourServlet
情况下, package com.example; public class YourServlet
,它必须位于/WEB-INF/classes/com/example/YourServlet.class
。 否则,如果@WebServlet
出现404错误,或者<servlet>
出现如下的HTTP 500错误,您将面对:
HTTP状态500
实例化servlet类com.example.YourServlet时出错
并在服务器日志中find一个java.lang.ClassNotFoundException: com.example.YourServlet
,接着是一个java.lang.NoClassDefFoundError: com.example.YourServlet
,然后是javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
。
validationservlet是否被正确编译并放置在classpath中的简单方法是让构build工具生成WAR文件(例如,右键单击项目,在Eclipse中导出> WAR文件 ),然后使用ZIP工具检查其内容。 如果/WEB-INF/classes
缺lessservlet /WEB-INF/classes
,那么项目configuration错误或某些IDE /项目configuration默认值被错误地还原(例如,在Eclipse中已经禁用了Project> Automatically )。 如果你不知道,最好是重新开始,不要碰任何IDE /项目configuration的默认值。
单独testingservlet
如果服务器在localhost:8080
上运行,并且WAR已成功部署在/contextname
的上下文path中(默认为IDE项目名,区分大小写!),并且该servlet没有失败其初始化(读取服务器logging任何部署/ servlet成功/失败消息以及实际的上下文path和servlet映射),那么可以在http://localhost:8080/contextname/servlet
使用URL模式为/servlet
http://localhost:8080/contextname/servlet
。
你可以直接在浏览器的地址栏中input它来不经意间进行testing。 如果它的doGet()
被正确覆盖并且被实现,那么你会在浏览器中看到它的输出。 或者,如果你没有任何doGet()
或者如果它不正确地调用super.doGet()
,那么将显示“ HTTP 405:HTTP方法GET不被这个URL支持 ”的错误(这仍然比404因为405certificate了servlet本身实际上是被发现的)。
重写service()
是一个不好的做法,除非你正在重新创build一个MVC框架 – 如果你刚刚开始使用servlet,并且对当前问题中描述的问题一无所知,这是不太可能的)另请参见Design Patterns web基于应用程序
无论如何,如果servlet在被testing的时候已经返回了404,那么用一个HTML表单来完全没有意义。 从逻辑上来说,将任何HTML表单包含在有关来自servlet的404错误的问题中也是毫无意义的。
从HTML引用servlet URL
一旦你确认servlet在单独调用的时候工作的很好,那么你可以前进到HTML。 至于你的HTML表单的具体问题, <form action>
值需要是一个有效的URL。 这同样适用于<a href>
。 您需要了解绝对/相对URL的工作方式。 您知道,url是url,您可以在网页浏览器的地址栏中input/查看。 如果您将相对URL指定为表单操作(即没有http://
scheme),那么它就相对于当前url,就像您在浏览器的地址栏中看到的那样。 因此,绝对不是与服务器的WAR文件夹结构中的JSP / HTML文件位置相关的,因为许多初学者似乎认为。
因此,假定带有HTML表单的JSP页面是通过http://localhost:8080/contextname/jsps/page.jsp
打开的,并且您需要提交到位于http://localhost:8080/contextname/servlet
,这里有几种情况(请注意,您可以用<a href>
here)安全地replace<form action>
:
-
表单操作提交到带有斜杠的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">
这将把一个文件夹(就像在本地磁盘文件系统path!),这样的forms将提交到
http://localhost:8080/contextname/servlet
这个必须工作!
-
但是,规范的方法是使URL相对于URL成为域名,以便在将JSP文件移动到另一个文件夹时,不需要再次修复URL。
<form action="${pageContext.request.contextPath}/servlet">
这会产生
<form action="/contextname/servlet">
这将始终提交到正确的url。
在HTML中使用直引号
您需要确保在HTML属性(如action="..."
或action='...'
使用直引号,从而不像action=”...”
或action='...'
那样使用引号action='...'
在HTML中不支持curl引号,它们将成为值的一部分。
也可以看看:
- 我们的servlets wiki页面 – 包含一些hello世界的例子
- 如何从HTML表单调用servlet类
- doGet和doPost在Servlets中
- 如何通过单击JSP页面中的超链接或button将当前项传递给Java方法?
其他HTTP状态404错误的情况下:
- HTTP状态404 – Servlet [ServletName]不可用
- HTTP状态404 – 请求的资源(/ ProjectName /)不可用
- HTTP状态404 – 请求的资源(/)不可用
- / WEB-INF中的JSP返回“HTTP状态404请求的资源不可用”
- 在JSP文件中引用放置在WEB-INF文件夹中的资源将返回资源上的HTTP 404
- 当调用转发给JSP的Servlet时,浏览器无法访问/查找CSS,图像和链接等相关资源