在我的数据库中,jsp文件中有一个html表单 WebContent/jsps
文件夹。我有一个servlet类 servlet.java
在我的默认包中 src
文件夹。在我的 web.xml
它被Map为 /servlet
.
我已经尝试了几个网址 action
html表单的属性:
<form action="/servlet">
<form action="/servlet.java">
<form action="/src/servlet.java">
<form action="../servlet.java">
但这些都不管用。它们都不断返回http 404错误,如tomcat 6/7/8中的以下错误:
http状态404-/servlet
描述:请求的资源(/servlet)不可用。
或如tomcat 8.5/9中所述:
http状态404-未找到
消息:/servlet
描述:源服务器找不到目标资源的当前表示形式,或者不愿意透露存在该表示形式
为什么它不起作用?
1条答案
按热度按时间ltqd579y1#
导言
这可能有很多原因,这些原因在以下章节中进行了分解:
将servlet类放入
package
在中设置servlet urlurl-pattern
@WebServlet
仅适用于servlet 3.0或更新版本javax.servlet.*
在servlet 5.0或更新版本中不再工作确保已编译
*.class
文件存在于内置war中在没有任何jsp/html页面的情况下单独测试servlet
使用域相对url从html引用servlet
在html属性中使用直接引号
将servlet类放入包中
首先,将servlet类放在java中
package
. 您应该始终将可公开重用的java类放在包中,否则它们对包中的类(例如服务器本身)是不可见的。这样可以消除潜在的特定于环境的问题。无包servlet只能在特定的tomcat+jdk组合中工作,这是不应该依赖的。对于“普通”ide项目,类需要放在其包结构中的“java源代码”文件夹中,而不是放在“web内容”文件夹中,该文件夹用于jsp等web文件。下面是一个默认eclipse动态web项目的文件夹结构示例,如navigator视图中所示(默认情况下,“java sources”文件夹位于该项目中,由
src
文件夹):对于maven项目,需要将类放置在其内部的包结构中
main/java
因此并非如此main/resources
,这是针对非类文件的,绝对不是main/webapp
,这是用于web文件的。下面是在eclipse的navigator视图中看到的默认maven webapp项目的文件夹结构示例:请注意
/jsps
子文件夹不是绝对必要的。您甚至可以不使用它,直接将jsp文件放在webcontent/webapp根目录中,但我只是从您的问题中接过这个问题。在url模式中设置servlet url
servlet url被指定为servletMap的“url模式”。根据定义,它绝对不是servlet类的类名/文件名。url模式将被指定为的值
@WebServlet
注解。如果您想支持路径参数,如
/servlet/foo/bar
,然后使用/servlet/*
相反另请参见servlet和路径参数,如/xyz/{value}/test,如何在web.xml中Map?@webservlet仅适用于servlet 3.0或更新版本
为了使用
@WebServlet
,您只需确保web.xml
文件(如果有)(由于servlet 3.0是可选的)被声明为符合servlet 3.0+版本,因此不符合servlet 2.5或更低版本。下面是一个与servlet 4.0兼容的版本(与tomcat 9+、wildfly 11+、payara 5+等匹配)。或者,如果您还没有使用servlet 3.0+(例如tomcat 6或更高版本),请删除
@WebServlet
注解。并在中注册servlet
web.xml
这样地:因此请注意,您不应同时使用这两种方法。使用基于注解的配置或基于xml的配置。如果两者都有,则基于xml的配置将覆盖基于注解的配置。
servlet.*在servlet 5.0或更新版本中不再工作
自雅加达ee 9/servlet 5.0(tomcat 10、tomee 9、wildfly 22预览版、glassfish 6、payara 6、liberty 22等)以来
javax.*
包已重命名为jakarta.*
包裹换句话说,请绝对确保不要仅仅为了获得
javax.*
要编译的包。这只会带来麻烦。将其全部删除,并从中编辑servlet类的导入到
如果您正在使用maven,您可以找到适当的示例
pom.xml
tomcat 10+、tomcat 9-、jee 9+和jee 8的声明-在这个回答中:tomcat将servlet转换为javax.servlet.servlet,而不是jakarta.servlet.http.httpservlet确保编译的*.class文件存在于内置war中
如果您使用的是eclipse和/或maven之类的构建工具,那么您需要绝对确保编译后的servlet类文件驻留在它的包结构中
/WEB-INF/classes
生成的war文件的文件夹。万一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中右键单击项目,导出>war文件),然后使用zip工具检查其内容。如果中缺少servlet类
/WEB-INF/classes
,或者如果导出导致错误,则说明项目配置不正确,或者错误地恢复了某些ide/项目配置默认值(例如,在eclipse中禁用了project>build automatically)。您还需要确保项目图标没有表示生成错误的红十字。您可以在问题视图(窗口>显示视图>其他…)中找到确切的错误。通常错误消息是很好的googlable。若你们并没有任何线索,最好是从头开始,不要碰任何ide/项目配置默认值。如果您正在使用eclipse,您可以在如何在eclipse项目中导入javax.servlet/jakarta.servlet api中找到说明?
在没有任何jsp/html页面的情况下单独测试servlet
如果服务器运行在
localhost:8080
,并且战争成功地部署在/contextname
(默认为ide项目名称,区分大小写!),servlet没有初始化失败(读取服务器日志中的任何部署/servlet成功/失败消息以及实际的上下文路径和servletMap),然后是url模式为的servlet/servlet
可于http://localhost:8080/contextname/servlet
.您可以直接在浏览器的地址栏中输入它,以不受干扰的方式进行测试。如果是
doGet()
正确重写和实现,然后您将在浏览器中看到其输出。或者如果你没有doGet()
或者如果它不正确地调用super.doGet()
,则会显示“http 405:http method get不受此url支持”错误(这仍然比404好,因为405是实际找到servlet本身的证据)。最重要的
service()
这是一种糟糕的做法,除非您正在重新创建一个mvc框架——如果您刚开始使用servlet,并且对当前问题中描述的问题一无所知,那么这是不可能的;)另请参见基于web的应用程序的设计模式。无论如何,如果servlet在进行独立测试时已经返回404,那么尝试使用html表单是完全没有意义的。因此,从逻辑上讲,在关于servlet 404错误的问题中包含任何html表单也是毫无意义的。
使用域相对url从html引用servlet
一旦您验证了servlet在单独调用时工作正常,那么就可以进入html。至于html表单的具体问题
<form action>
值必须是有效的url。这同样适用于<a href>
. 您需要了解绝对/相对URL是如何工作的。你知道,url是一个网址,你可以在webbrowser的地址栏中输入/查看。如果将相对url指定为表单操作,即没有http://
方案,然后它将成为相对于当前url的,如您在webbrowser的地址栏中看到的。因此,它与服务器war文件夹结构中的jsp/html文件位置绝对不是像许多初学者所认为的那样相关。因此,假设带有html表单的jsp页面是由
http://localhost:8080/contextname/jsps/page.jsp
(因此不是通过file://...
),您需要提交到位于http://localhost:8080/contextname/servlet
,以下是几种情况(请注意,您可以安全地替换<form action>
具有<a href>
此处):表单操作提交到带有前导斜杠的url。
前导斜杠
/
使url相对于域,因此表单将提交到但这可能会导致404,因为它在错误的上下文中。
表单操作提交到不带前导斜杠的url。
这使得url相对于当前url的当前文件夹,因此表单将提交到
但这可能会导致404,因为它位于错误的文件夹中。
表单操作提交到一个url,该url向上移动一个文件夹。
这将向上移动一个文件夹(与本地磁盘文件系统路径完全相同!),因此,表格将提交给
这个一定有用!
然而,规范的方法是使url域相对,这样当您碰巧将jsp文件移动到另一个文件夹中时,就不需要再次修复url。
这将产生
因此,它将始终提交到正确的url。
在html属性中使用直接引号
您需要绝对确保在html属性中使用直接引号,如
action="..."
或action='...'
因此不是像这样的 curl 引号action=”...”
或action=’...’
. html中不支持 curl 引号,它们只会成为值的一部分。从博客复制粘贴代码片段时要小心!一些b