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

nwlqm0z1  于 2022-09-21  发布在  Eclipse
关注(0)|答案(19)|浏览(372)

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

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

<form action="/servlet">
<form action="/servlet.java">
<form action="/src/servlet.java">
<form action="../servlet.java">

但这些都不管用。在Tomcat 6/7/8中,它们都一直返回如下所示的HTTP404错误:

HTTP状态404--/Servlet

  • 说明*:请求的资源(/Servlet)不可用。

或在Tomcat 8.5/9中如下所示:

HTTP状态404-未找到

  • Message*:/Servlet

  • Description*:源站没有找到目标资源的当前表示,或者不愿意透露存在

或者在Tomcat 10中如下所示:

HTTP状态404-未找到

  • 类型*:状态报告

  • 消息*:请求的资源(/Servlet)不可用

  • Description*:源站没有找到目标资源的当前表示,或者不愿意透露存在

为什么它不起作用?

bmp9r5qi

bmp9r5qi1#

首先,以管理员身份运行您的IDE。之后,右键单击项目文件夹->Project facets并确保Java版本设置正确。在我的电脑上。(例如1.8)现在它应该可以工作了。

不要只使用cmd启动您的服务器,例如WildFly。它必须在IDE中启动,现在访问您的本地主机URL。示例:http://localhost:8080/HelloWorldServlet/HelloWorld

emeijp43

emeijp432#

请检查上下文根不能为空

如果您使用的是eclipse:

右键单击,选择属性,然后选择Web项目设置。勾选上下文根不能为空

ni65a41a

ni65a41a3#

我也有同样的问题。我正在开发一个基于MVC的REST API,其中没有显式的html配置或文件。该API使用Swagger来生成用户界面。当我引入Swagger版本“3.0.0”时,问题就开始了。我恢复到Swagger“2.9.2”,这解决了我的问题。

<!-- Swagger -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
ufj5ltwl

ufj5ltwl4#

我也有同样的问题。我试过了所有的方法,但都没有用。通过在XML文件的开头和结尾添加元素标记,我设法解决了这个问题。我将在下面留下我的XML文件以供参考。

<?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>
yfwxisqw

yfwxisqw5#

我也面临着这个问题,当我访问一个我知道链接到Servlet的URL模式时,我收到了一个404。原因是我有两个Servlet,它们的@WebServlet name参数设置为相同的字符串。

@WebServlet(name = "ServletName", urlPatterns = {"/path"})
public class ServletName extends HttpServlet {}
@WebServlet(name = "ServletName", urlPatterns = {"/other-path"})
public class OtherServletName extends HttpServlet {}

两个name参数相同。如果您使用的是name参数,请确保与应用程序上的所有其他Servlet相比,它们是唯一的。

ttisahbt

ttisahbt6#

如果您是一名学生并且是Java的新手,那么您的web.xml文件可能会出现一些问题。
1.尝试删除web.xml文件。
1.其次,检查您的PATH变量是否设置正确。
1.重启Tomcat服务器或PC。

你的问题一定会得到解决。

umuewwlo

umuewwlo7#

如果有人在这里使用MySQL,并且觉得前一天代码工作正常,但现在它不工作,那么我想您必须打开MySQL CLI或MySQL工作台,只连接到数据库一次。一旦连接上,数据库也会连接到Java应用程序。我过去常常收到Hibernate方言错误,指出com.mysql.jdbc.Diverer有问题。我认为某些计算机上的MySQL存在启动问题。这对我来说解决了。

im9ewurl

im9ewurl8#

在web.xml中Map是我所做的:-

1.如果有为新计划制定的另一个一揽子计划,那么我们必须提到:

在XML文件中Servlet类标记的开始和结束之间的Packagename.filename。

1.如果您以XML格式Map文件,但这些文件不工作或显示错误,则在相应文件中的代码注解行上进行注解。

这两种方法互不兼容,所以我要么使用创建Servlet时提到的文件的注解方法,要么使用Map的方式,然后删除或注解注解行。例如:

<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>

如果完成了XML中的Map,则注解相应文件中的代码的注解行。

//@WebServlet("/FirstServ")
//@WebServlet("/SecondServ")
tjrkku2a

tjrkku2a9#

如果您不想使用‘Form’和‘Submit’按钮来打开一个带有Java脚本的Servlet,下面的代码如下:

var button = document.getElementById("<<button-id>>");
button.addEventListener("click", function() {
  window.location.href= "<<full-servlet-path>>" (eg. http://localhost:8086/xyz/servlet)
});

密钥:

1)Button-id:您在html/jsp文件中为按钮提供的‘id’标记。

2)Full-Servlet-Path:单独运行Servlet时在浏览器中显示的路径

rhfm7lfc

rhfm7lfc10#

对我有效的修复方法是(如果您使用的是Maven):右键单击您的项目,Maven->更新项目。这可能会给您的JDK和其他库(在我的例子中,MySQL连接器)带来一些其他错误,但是一旦您修复了它们,您的原始问题就应该被修复了!

7vhp5slm

7vhp5slm11#

Introduction

This can have a lot of causes which are broken down in following sections:

  • Put servlet class in a package
  • Set servlet URL in url-pattern
  • @WebServlet works only on Servlet 3.0 or newer
  • javax.servlet.* doesn't work anymore in Servlet 5.0 or newer
  • Make sure compiled *.class file is present in built WAR
  • Test the servlet individually without any JSP/HTML page
  • Use domain-relative URL to reference servlet from HTML
  • Use straight quotes in HTML attributes

Put servlet class in a package

First of all, put the servlet class in a Java package. You should always put publicly reuseable Java classes in a package, otherwise they are invisible to classes which are in a package, such as the server itself. This way you eliminate potential environment-specific problems. Packageless servlets work only in specific Tomcat+JDK combinations and this should never be relied upon.

In case of a "plain" IDE project, the class needs to be placed in its package structure inside the "Java Sources" folder, not inside "Web Content" folder, which is for web files such as JSP. Below is an example of the folder structure of a default Eclipse Dynamic Web Project as seen in Navigator view (the "Java Sources" folder is in such project by default represented by src folder):

EclipseProjectName
 |-- src
 |    `-- com
 |         `-- example
 |              `-- YourServlet.java
 |-- WebContent
 |    |-- WEB-INF
 |    |    `-- web.xml
 |    `-- jsps
 |         `-- page.jsp
 :

In case of a Maven project, the class needs to be placed in its package structure inside main/java and thus notmain/resources, this is for non-class files and absolutely also notmain/webapp, this is for web files. Below is an example of the folder structure of a default Maven webapp project as seen in Eclipse's Navigator view:

MavenProjectName
 |-- src
 |    `-- main
 |         |-- java
 |         |    `-- com
 |         |         `-- example
 |         |              `-- YourServlet.java
 |         |-- resources
 |         `-- webapp
 |              |-- WEB-INF
 |              |    `-- web.xml
 |              `-- jsps
 |                   `-- page.jsp
 :

Note that the /jsps subfolder is not strictly necessary. You can even do without it and put the JSP file directly in webcontent/webapp root, but I'm just taking over this from your question.

Set servlet URL in url-pattern

The servlet URL is specified as the "URL pattern" of the servlet mapping. It's absolutely not per definition the classname/filename of the servlet class. The URL pattern is to be specified as value of @WebServlet annotation.

package com.example; // Use a package!

import jakarta.servlet.annotation.WebServlet; // or javax.*
import jakarta.servlet.http.HttpServlet; // or javax.*

@WebServlet("/servlet") // This is the URL of the servlet.
public class YourServlet extends HttpServlet { // Must be public and extend HttpServlet.
    // ...
}

In case you want to support path parameters like /servlet/foo/bar, then use an URL pattern of /servlet/* instead. See also Servlet and path parameters like /xyz/{value}/test, how to map in web.xml?

@WebServlet works only on Servlet 3.0 or newer

In order to use @WebServlet, you only need to make sure that your web.xml file, if any (it's optional since Servlet 3.0), is declared conform Servlet 3.0+ version and thus not conform e.g. 2.5 version or lower. Below is a Servlet 5.0 compatible one (which matches Tomcat 10+, WildFly 22+ (Preview), GlassFish/Payara 6+, etc).

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
    version="5.0">

    <!-- Config here. -->
</web-app>

And below is a Servlet 4.0 compatible one (which matches Tomcat 9+, WildFly 11+, GlassFish/Payara 5+, etc).

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
    version="4.0"
>
    <!-- Config here. -->
</web-app>

Or, in case you're not on Servlet 3.0+ yet (e.g. Tomcat 6 or older), then remove the @WebServlet annotation.

package com.example;

import javax.servlet.http.HttpServlet;

public class YourServlet extends HttpServlet {
    // ...
}

And register the servlet instead in web.xml like this:

<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>

Note thus that you should not use both ways. Use either annotation based configuarion or XML based configuration. When you have both, then XML based configuration will override annotation based configuration.

javax.servlet.* doesn't work anymore in Servlet 5.0 or newer

Since Jakarta EE 9 / Servlet 5.0 (Tomcat 10, TomEE 9, WildFly 22 Preview, GlassFish 6, Payara 6, Liberty 22, etc), the javax.* package has been renamed to jakarta.* package.

In other words, please make absolutely sure that you don't randomly put JAR files of a different server in your WAR project such as tomcat-servlet-api-9.x.x.jar merely in order to get the javax.* package to compile. This will only cause trouble. Remove it altogether and edit the imports of your servlet class from

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

to

import jakarta.servlet.*;
import jakarta.servlet.annotation.*;
import jakarta.servlet.http.*;

In case you're using Maven, you can find examples of proper pom.xml declarations for Tomcat 10+, Tomcat 9-, JEE 9+ and JEE 8- in this answer: Tomcat casting servlets to javax.servlet.Servlet instead of jakarta.servlet.http.HttpServlet. The alternative is to downgrade the server to an older version, e.g. from Tomcat 10 back to Tomcat 9 or older, but this is clearly not the recommended way to go.

Make sure compiled *.class file is present in built WAR

In case you're using a build tool such as Eclipse and/or Maven, then you need to make absolutely sure that the compiled servlet class file resides in its package structure in /WEB-INF/classes folder of the produced WAR file. In case of package com.example; public class YourServlet, it must be located in /WEB-INF/classes/com/example/YourServlet.class. Otherwise you will face in case of @WebServlet also a 404 error, or in case of <servlet> a HTTP 500 error like below:

HTTP Status 500

Error instantiating servlet class com.example.YourServlet

And find in the server log a java.lang.ClassNotFoundException: com.example.YourServlet, followed by a java.lang.NoClassDefFoundError: com.example.YourServlet, in turn followed by jakarta.servlet.ServletException: Error instantiating servlet class com.example.YourServlet.

An easy way to verify if the servlet is correctly compiled and placed in classpath is to let the build tool produce a WAR file (e.g. rightclick project, Export > WAR file in Eclipse) and then inspect its contents with a ZIP tool. If the servlet class is missing in /WEB-INF/classes, or if the export causes an error, then the project is badly configured or some IDE/project configuration defaults have been mistakenly reverted (e.g. Project > Build Automatically has been disabled in Eclipse).

You also need to make sure that the project icon has no red cross indicating a build error. You can find the exact error in Problems view (Window > Show View > Other...). Usually the error message is fine Googlable. In case you have no clue, best is to restart from scratch and do not touch any IDE/project configuration defaults. In case you're using Eclipse, you can find instructions in How do I import the javax.servlet / jakarta.servlet API in my Eclipse project?

Test the servlet individually without any JSP/HTML page

Provided that the server runs on localhost:8080, and that the WAR is successfully deployed on a context path of /contextname (which defaults to the IDE project name, case sensitive!), and the servlet hasn't failed its initialization (read server logs for any deploy/servlet success/fail messages and the actual context path and servlet mapping), then a servlet with URL pattern of /servlet is available at http://localhost:8080/contextname/servlet.

You can just enter it straight in browser's address bar to test it invidivually. If its doGet() is properly overriden and implemented, then you will see its output in browser. Or if you don't have any doGet() or if it incorrectly calls super.doGet(), then a "HTTP 405: HTTP method GET is not supported by this URL" error will be shown (which is still better than a 404 as a 405 is evidence that the servlet itself is actually found).

Overriding service() is a bad practice, unless you're reinventing a MVC framework — which is very unlikely if you're just starting out with servlets and are clueless as to the problem described in the current question ;) See also Design Patterns web based applications.

Regardless, if the servlet already returns 404 when tested invidivually, then it's entirely pointless to try with a HTML form instead. Logically, it's therefore also entirely pointless to include any HTML form in questions about 404 errors from a servlet.

Use domain-relative URL to reference servlet from HTML

Once you've verified that the servlet works fine when invoked individually, then you can advance to HTML. As to your concrete problem with the HTML form, the <form action> value needs to be a valid URL. The same applies to <a href>, <img src>, <script src>, etc. You need to understand how absolute/relative URLs work. You know, an URL is a web address as you can enter/see in the webbrowser's address bar. If you're specifying a relative URL as form action, i.e. without the http:// scheme, then it becomes relative to the current URL as you see in your webbrowser's address bar. It's thus absolutely not relative to the JSP/HTML file location in server's WAR folder structure as many starters seem to think.

So, assuming that the JSP page with the HTML form is opened by http://localhost:8080/contextname/jsps/page.jsp (and thusnotby file://...), and you need to submit to a servlet located in http://localhost:8080/contextname/servlet, here are several cases (note that you can here safely substitute <form action> with <a href>, <img src>, <script src>, etc):

  • Form action submits to an URL with a leading slash.
<form action="/servlet">

The leading slash / makes the URL relative to the domain, thus the form will submit to

http://localhost:8080/servlet

But this will likely result in a 404 as it's in the wrong context.

  • Form action submits to an URL without a leading slash.
<form action="servlet">

This makes the URL relative to the current folder of the current URL, thus the form will submit to

http://localhost:8080/contextname/jsps/servlet

But this will likely result in a 404 as it's in the wrong folder.

  • Form action submits to an URL which goes one folder up.
<form action="../servlet">

This will go one folder up (exactly like as in local disk file system paths!), thus the form will submit to

http://localhost:8080/contextname/servlet

This one must work!

  • The canonical approach, however, is to make the URL domain-relative so that you don't need to fix the URLs once again when you happen to move the JSP files around into another folder.
<form action="${pageContext.request.contextPath}/servlet">

This will generate

<form action="/contextname/servlet">

Which will thus always submit to the right URL.

Use straight quotes in HTML attributes

You need to make absolutely sure you're using straight quotes in HTML attributes like action="..." or action='...' and thus not curly quotes like action=”...” or action=’...’. Curly quotes are not supported in HTML and they will simply become part of the value. Watch out when copy-pasting code snippets from blogs! Some blog engines, notably Wordpress, are known to by default use so-called "smart quotes" which thus also corrupts the quotes in code snippets this way. On the other hand, instead of copy-pasting code, try simply typing over the code yourself. Additional advantage of actually getting the code through your brain and fingers is that it will make you to remember and understand the code much better in long term and also make you a better developer.

See also:

Other cases of HTTP Status 404 error:

sczxawaw

sczxawaw12#

一个老帖子,但由于我在其他地方找不到它,这里还有一个可能性:

如果您使用的是Servlet-API 3.0+,则您的web.xml必须不包含metadata-complete="true"属性

这告诉Tomcat使用web.xml中给出的数据来MapServlet,而不是使用@WebServlet注解。

k4ymrczo

k4ymrczo13#

我删除了旧的Web库,它们是Spring框架库。并构建了一条新的图书馆路径。那它就起作用了。

xqkwcwgp

xqkwcwgp14#

执行以下两个步骤。希望能够解决Java Servlet应用开发过程中Tomcat服务器“404找不到”的问题。

步骤1:Right click on the server(in the server explorer tab)->Properties->Switch Location from workspace metadata to tomcat server

步骤2:Double Click on the server(in the server explorer tab)->Select Use tomcat installation option inside server location menu

js81xvg6

js81xvg615#

我的问题是我的方法缺少@RequestBody注解。添加注解后,我不再收到404异常。

相关问题