我的 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 回答
将servlet类放在包中
首先,将servlet类放在Java
package
中 . 您应该始终将公开可重用的Java类放在一个包中,否则它们对于包中的类是不可见的,例如服务器本身 . 这样您就可以消除潜在的特定于环境的问题 . 无包装servlet仅适用于特定的Tomcat JDK组合,绝不应该依赖它 .对于"plain" IDE项目,该类需要放在"Java Resources"文件夹内的包结构中,因此不需要"WebContent",这适用于JSP等Web文件 . 下面是Navigator视图中显示的默认Eclipse Dynamic Web Project的文件夹结构示例:
对于Maven项目,该类需要放在
main/java
and thus not e.g. main/resources, this is for non-class files内的包结构中 . 下面是Eclipse的Navigator视图中显示的默认Maven webapp项目的文件夹结构示例:请注意,
/jsps
子文件夹不是严格必需的 . 你甚至可以不用它并将JSP文件直接放在webcontent / webapp root中,但我只是从你的问题中接过这个 .在url-pattern中设置servlet URL
servlet URL指定为servlet映射的"URL pattern" . 绝对不是每个定义servlet类的类名/文件名 . URL模式将指定为
@WebServlet
注释的值 .如果您想支持
/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等相匹配) .或者,如果您尚未使用Servlet 3.0(不是Tomcat 7或更新版本,但Tomcat 6或更早版本),则删除
@WebServlet
注释 .并在_758056中注册servlet,如下所示:
因此请注意,您不应该使用这两种方式 . 使用基于注释的配置或基于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错误,如下所示:并在服务器日志中找到
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相对于域,因此表单将提交给但这可能会导致404,因为它处于错误的上下文中 .
这使得URL相对于当前URL的当前文件夹,因此表单将提交给
但这可能会导致404,因为它在错误的文件夹中 .
这将是一个文件夹(完全像在本地磁盘文件系统路径!),因此表单将提交
这个必须工作!
但是,规范方法是使URL相对于域,这样当您将JSP文件移动到另一个文件夹时,就不需要再次修复URL .
这将产生
因此,它将始终提交到正确的URL .
在HTML中使用直引号
您需要确保在
action="..."
或action='...'
等HTML属性中使用直引号,因此不能使用action=”...”
或action=’...’
等引号 . HTML中不支持卷曲引号,它们只会成为值的一部分 .另见:
Our servlets wiki page - 包含一些hello world示例
How to call servlet class from HTML form
doGet and doPost in Servlets
How do I pass current item to Java method by clicking a hyperlink or button in JSP page?
HTTP状态404错误的其他情况:
HTTP Status 404 - Servlet [ServletName] is not available
HTTP Status 404 - The requested resource (/ProjectName/) is not available
HTTP Status 404 - The requested resource (/) is not available
JSP in /WEB-INF returns "HTTP Status 404 The requested resource is not available"
Referencing a resource placed in WEB-INF folder in JSP file returns HTTP 404 on resource
Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP
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 .
我遇到了:
以下是场景#3的更多详细信息:
SCENARIO 3.1:web.xml文件中的servlet类包路径错误 .
它应该在java servlet的顶部匹配package语句类 .
文件:my_stuff / MyClass.java :
文件:PRJ_ROOT / src / main / webapp / WEB-INF / web.xml
情景3.2:
您将错误的“ package ”语句放在myClass.java文件的顶部 .
例如:
文件位于:“ /my_stuff ”文件夹中
你错误地写道:
这很棘手,因为:
1:maven build(mvn包)不会在此报告任何错误 .
2:web.xml中的servlet-class行可以有CORRECT包路径 . 例如:
使用的堆栈: Notepad++ GitBash Maven Heroku Web App Runner Tomcat9 Windows10 :
NetBeans IDE中
HTTP Status 404
的解决方案:右键单击项目并转到项目属性,然后单击运行,然后输入项目相对URL,如index.jsp
.项目 - >属性
点击“运行”
相对URL:/index.jsp(选择项目根URL)