El servlet devuelve "Estado HTTP 404 El recurso solicitado (/ servlet) no está disponible"


95

Tengo un formulario HTML en un archivo JSP en mi WebContent/jspscarpeta. Tengo una clase de servlet servlet.javaen mi paquete predeterminado en la srccarpeta. En mi web.xmlestá mapeado como /servlet.

He probado varias URL en el actionatributo del formulario HTML:

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

Pero ninguno de esos funciona. Todos siguen devolviendo un error HTTP 404 como se muestra a continuación en Tomcat 6/7/8:

Estado HTTP 404 - / servlet

Descripción : el recurso solicitado (/ servlet) no está disponible.

O como se muestra a continuación en Tomcat 8.5 / 9:

Estado HTTP 404: no encontrado

Mensaje : / servlet

Descripción : el servidor de origen no encontró una representación actual para el recurso de destino o no está dispuesto a revelar que existe.

¿Por qué no funciona?

Respuestas:


127

Ponga la clase de servlet en un package

En primer lugar, coloque la clase de servlet en Java package. Usted debe siempre poner clases reutilizables públicamente Java en un paquete, si no que son invisibles a las clases que se encuentran en un paquete, como el propio servidor. De esta forma, elimina posibles problemas específicos del entorno. Los servlets sin paquete funcionan solo en combinaciones específicas de Tomcat + JDK y nunca se debe confiar en esto.

En el caso de un proyecto IDE "simple", la clase debe colocarse en su estructura de paquete dentro de la carpeta "Recursos Java" y, por lo tanto, no en "WebContent", esto es para archivos web como JSP. A continuación se muestra un ejemplo de la estructura de carpetas de un proyecto web dinámico de Eclipse predeterminado como se ve en la vista del navegador :

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

En el caso de un proyecto Maven, la clase debe colocarse en su estructura de paquete dentro main/java y, por lo tanto, nomain/resources , por ejemplo , esto es para archivos que no son de clase . A continuación se muestra un ejemplo de la estructura de carpetas de un proyecto de aplicación web Maven predeterminado como se ve en la vista del navegador de Eclipse :

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

Tenga en cuenta que la /jspssubcarpeta no es estrictamente necesaria. Incluso puede prescindir de él y poner el archivo JSP directamente en la raíz webcontent / webapp, pero solo me estoy haciendo cargo de esto de su pregunta.

Establecer URL de servlet en url-pattern

La URL del servlet se especifica como el "patrón de URL" del mapeo del servlet. No es en absoluto, por definición, el nombre de clase / nombre de archivo de la clase de servlet. El patrón de URL se especificará como valor de @WebServletanotación.

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.
    // ...
}

En caso de que desee admitir parámetros de ruta como /servlet/foo/bar, utilice un patrón de URL de /servlet/*. Vea también Servlet y parámetros de ruta como / xyz / {value} / test, ¿cómo mapear en web.xml?

@WebServlet funciona solo en Servlet 3.0 o más reciente

Para usarlo @WebServlet, solo necesita asegurarse de que su web.xmlarchivo, si lo hay (es opcional desde Servlet 3.0), se declara conforme con la versión Servlet 3.0+ y, por lo tanto, no es conforme, por ejemplo, la versión 2.5 o inferior . A continuación se muestra uno compatible con Servlet 4.0 (que coincide con Tomcat 9+, WildFly 11+, 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>

O, en caso de que aún no esté en Servlet 3.0+ (por ejemplo, Tomcat 6 o anterior), elimine la @WebServletanotación.

package com.example;

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

Y registre el servlet en su lugar web.xmlasí:

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

Por lo tanto, tenga en cuenta que no debe utilizar ambas formas. Utilice una configuración basada en anotaciones o una configuración basada en XML. Cuando tenga ambos, la configuración basada en XML anulará la configuración basada en anotaciones.

Verificando la construcción / implementación

En caso de que esté utilizando una herramienta de compilación como Eclipse y / o Maven, debe asegurarse absolutamente de que el archivo de clase de servlet compilado resida en su estructura de paquete en la /WEB-INF/classescarpeta del archivo WAR producido. En caso de package com.example; public class YourServlet, debe estar ubicado en /WEB-INF/classes/com/example/YourServlet.class. De lo contrario, se enfrentará también en caso de @WebServletun error 404, o en caso de <servlet>un error HTTP 500 como el siguiente:

Estado HTTP 500

Error al crear una instancia de la clase de servlet com.example.YourServlet

Y busque en el registro del servidor a java.lang.ClassNotFoundException: com.example.YourServlet, seguido de a java.lang.NoClassDefFoundError: com.example.YourServlet, seguido de javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet.

Una manera fácil de verificar si el servlet está correctamente compilado y colocado en classpath es dejar que la herramienta de compilación produzca un archivo WAR (por ejemplo, haga clic con el botón derecho en el proyecto, Exportar> Archivo WAR en Eclipse) y luego inspeccione su contenido con una herramienta ZIP. Si falta la clase de servlet /WEB-INF/classes, o si la exportación causa un error, entonces el proyecto está mal configurado o algunos valores predeterminados de configuración de IDE / proyecto se han revertido por error (por ejemplo, Proyecto> Construir automáticamente se ha deshabilitado en Eclipse).

También debe asegurarse de que el icono del proyecto no tenga una cruz roja que indique un error de compilación. Puede encontrar el error exacto en la vista Problemas ( Ventana> Mostrar vista> Otro ... ). Por lo general, el mensaje de error se puede buscar en Google. En caso de que no tenga ni idea, lo mejor es reiniciar desde cero y no tocar ningún IDE / configuración predeterminada del proyecto. En caso de que esté utilizando Eclipse, puede encontrar instrucciones en ¿Cómo importo la API javax.servlet en mi proyecto Eclipse?

Probando el servlet individualmente

Siempre que el servidor se ejecute localhost:8080y que el WAR se implemente con éxito en una ruta de contexto de /contextname(que por defecto es el nombre del proyecto IDE, distingue entre mayúsculas y minúsculas), y el servlet no ha fallado en su inicialización (lea los registros del servidor para cualquier implementación / mensajes de éxito / error del servlet y la ruta de contexto real y el mapeo del servlet), entonces hay un servlet con el patrón de URL /servletdisponible en http://localhost:8080/contextname/servlet.

Puede ingresarlo directamente en la barra de direcciones del navegador para probarlo de forma individual. Si doGet()se reemplaza e implementa correctamente, verá su salida en el navegador. O si no tiene ninguno doGet()o si llama incorrectamente super.doGet(), se mostrará un error " HTTP 405: el método HTTP GET no es compatible con esta URL " (que es mejor que un 404, ya que un 405 es evidencia de que el servlet sí mismo se encuentra realmente).

Anular service()es una mala práctica, a menos que esté reinventando un marco MVC, lo cual es muy poco probable si recién está comenzando con servlets y no tiene ni idea del problema descrito en la pregunta actual;) Consulte también Diseñar patrones de aplicaciones basadas en web .

Independientemente, si el servlet ya devuelve 404 cuando se prueba de forma individual, entonces no tiene sentido intentarlo con un formulario HTML. Lógicamente, por lo tanto, tampoco tiene sentido incluir ningún formulario HTML en preguntas sobre errores 404 de un servlet.

Hacer referencia a la URL del servlet desde HTML

Una vez que haya verificado que el servlet funciona bien cuando se invoca individualmente, puede avanzar a HTML. En cuanto a su problema concreto con el formulario HTML, el <form action>valor debe ser una URL válida. Lo mismo se aplica a <a href>. Debe comprender cómo funcionan las URL absolutas / relativas. Ya sabes, una URL es una dirección web que puedes ingresar / ver en la barra de direcciones del navegador web. Si especifica una URL relativa como acción de formulario, es decir, sin el http://esquema, entonces se vuelve relativa a la URL actual como ve en la barra de direcciones de su navegador web. Por lo tanto, no es en absoluto relativo a la ubicación del archivo JSP / HTML en la estructura de carpetas WAR del servidor, como parecen pensar muchos principiantes.

Entonces, asumiendo que la página JSP con el formulario HTML es abierta por http://localhost:8080/contextname/jsps/page.jsp, y necesita enviarla a un servlet ubicado en http://localhost:8080/contextname/servlet, aquí hay varios casos (tenga en cuenta que puede sustituir <form action>con seguridad <a href>aquí):

  • La acción del formulario se envía a una URL con una barra inclinada.

    <form action="/servlet">

    La barra inclinada /hace que la URL sea relativa al dominio, por lo que el formulario se enviará a

    http://localhost:8080/servlet

    Pero esto probablemente resultará en un 404 ya que está en el contexto incorrecto.


  • La acción de formulario se envía a una URL sin una barra inclinada.

    <form action="servlet">

    Esto hace que la URL sea relativa a la carpeta actual de la URL actual, por lo que el formulario se enviará a

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

    Pero esto probablemente resultará en un 404 ya que está en la carpeta incorrecta.


  • La acción del formulario se envía a una URL que sube una carpeta.

    <form action="../servlet">

    Esto subirá una carpeta (¡exactamente como en las rutas del sistema de archivos del disco local!), Por lo que el formulario se enviará a

    http://localhost:8080/contextname/servlet

    ¡Este debe funcionar!


  • El enfoque canónico, sin embargo, es hacer que la URL sea relativa al dominio para que no necesite corregir las URL una vez más cuando mueva los archivos JSP a otra carpeta.

    <form action="${pageContext.request.contextPath}/servlet">

    Esto generará

    <form action="/contextname/servlet">

    Por lo tanto, siempre se enviará a la URL correcta.


Utilice comillas rectas en HTML

Debe asegurarse absolutamente de que está utilizando comillas rectas en atributos HTML como action="..."o action='...'y, por lo tanto, no comillas como action=”...”o action=’...’. Las comillas curvas no son compatibles con HTML y simplemente se convertirán en parte del valor.

Ver también:

Otros casos de error HTTP Status 404:


1
web-app version = "3.1" usando glassfish, pude probar mi servlet individualmente bien cuando tenía un mapeo en web.xml Y la anotación. Eliminé el mapeo y dejé la anotación ya que tengo la última versión, pero luego obtendría un error 404.
SallyRothroat

1
Eso puede suceder si incluye servlet 2.5 o bibliotecas anteriores en la propia aplicación web en lugar de depender del tiempo de ejecución de destino para proporcionar las bibliotecas de servlet por sí mismo.
BalusC

@xdola: De hecho, es frágil porque depende del URI de la solicitud. Simplemente lea la respuesta para obtener la explicación de su problema y cuál es el enfoque correcto.
BalusC

4

Escenario # 1: Usted accidentalmente volver a desplegarse desde la línea de comandos, mientras que Tomcat se está ejecutando .

Respuesta corta: Detenga Tomcat, elimine la carpeta de destino , el paquete mvn y luego vuelva a implementar


Escenario n. ° 2: request.getRequestDispatcher (" MIS_SPELLED_FILE_NAME .jsp ")

Respuesta corta: Verifique la ortografía del nombre del archivo , asegúrese de que el caso sea ​​correcto.


Escenario n. ° 3: Excepciones de clase no encontrada (la respuesta se puso aquí porque: Pregunta n. ° 17982240) ( java.lang.ClassNotFoundException para servlet en tomcat con eclipse ) (se marcó como duplicado y me dirigió aquí)

Respuesta corta # 3.1: web.xml tiene una ruta de paquete incorrecta en la etiqueta de clase de servlet.

Respuesta corta # 3.2: el archivo java tiene una declaración de importación incorrecta.


A continuación se muestran más detalles para el escenario n. ° 1:


1: Detén a Tomcat

  • Opción 1: vía CTRL + C en la terminal.
  • Opción 2: (terminal cerrada mientras Tomcat aún se está ejecutando)
  • ------------ 2.1: presione: Windows + R -> escriba: " services.msc "
  • ------------ 2.2: Busque "Apache Tomcat #. # Tomcat #" en la columna Nombre de la lista.
  • ------------ 2.3: Clic derecho -> " detener "

2: Elimina la carpeta "destino". (mvn clean no te ayudará aquí)

3: paquete mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE

(Mío: java -jar target / dependency / webapp-runner.jar --port 5190 target / *. War)

Historia completa:


Abrí accidentalmente una nueva ventana de git-bash e intenté implementar un archivo .war para mi proyecto heroku a través de:

java -jar target / dependency / webapp-runner.jar --port 5190 target / *. war

Después de una falla en la implementación, me di cuenta de que tenía dos ventanas git-bash abiertas y no había usado CTLR + C para detener la implementación anterior .

Me encontré con:

Estado HTTP 404 - Informe de estado de tipo no encontrado

Mensaje /if-student-test.jsp

Descripción El servidor de origen no encontró una representación actual para el recurso de destino o no está dispuesto a revelar que existe.

Apache Tomcat / 8.5.31

A continuación se muestran más detalles para el escenario n. ° 3:


ESCENARIO 3.1: La ruta del paquete de clase servlet es incorrecta en su archivo web.xml.

Debe COINCIDIR con la declaración del paquete en la parte superior de su clase de servlet java.

Archivo: my_stuff / MyClass.java :

   package my_stuff;

Archivo: PRJ_ROOT / src / main / webapp / WEB-INF / web.xml

   <servlet-class>
   my_stuff.MyClass
   </servlet-class>

ESCENARIO 3.2:

Pones la declaración " paquete " incorrecta en la parte superior de tu archivo myClass.java.

Por ejemplo:

El archivo está en: carpeta " / my_stuff "

Escribes por error:

package com.my_stuff

Esto es complicado porque:

1: La compilación de maven (paquete mvn) no informará ningún error aquí.

2: la línea de clase de servlet en web.xml puede tener la ruta CORRECTA del paquete. P.ej:

<servlet-class>
my_stuff.MyClass
</servlet-class>

Pila utilizada: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10 :


Su AppName.war y, por lo tanto, el nombre de la carpeta expandida no coincide con el nombre esperado, por ejemplo, cuando su archivo war tiene una versión como AppName-1.0-SNAPSHOT.war y está intentando / AppName /.
jla

0

Solución para HTTP Status 404en NetBeans IDE: Haga clic derecho en su proyecto y vaya a las propiedades de su proyecto, luego haga clic en ejecutar, luego ingrese la URL relativa de su proyecto como index.jsp.

  1. Proyecto-> Propiedades
  2. Haga clic en Ejecutar
  3. URL relativa: /index.jsp (seleccione la URL raíz de su proyecto)

ingrese la descripción de la imagen aquí


0

Mi problema fue que a mi método le faltaba la anotación @RequestBody. Después de agregar la anotación, ya no recibí la excepción 404.


0

Realice los siguientes dos pasos. Espero que resuelva el problema "404 no encontrado" en el servidor tomcat durante el desarrollo de la aplicación de servlet Java.

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

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


0

Eliminé la antigua biblioteca web, que son bibliotecas de marco de primavera. Y construye un nuevo camino de las bibliotecas. Entonces funciona.


0

Un hilo antiguo, pero como no lo encontré en otro lugar, aquí hay una posibilidad más:

Si está utilizando servlet-api 3.0+ , entonces su web.xml NO debe incluir el metadata-complete="true"atributo

ingrese la descripción de la imagen aquí

Esto le dice a Tomcat que mapee los servlets usando los datos proporcionados en web.xmllugar de usar la @WebServletanotación.


0

En primer lugar, ejecute su IDE como administrador. Después de eso, haga clic con el botón derecho en la carpeta del proyecto -> Facetas del proyecto y asegúrese de que la versión de Java esté configurada correctamente. En mi PC. (Por ejemplo 1.8) Ahora debería funcionar.

No inicie simplemente su servidor, por ejemplo Wildfly, usando el cmd. Debe iniciarse dentro del IDE y ahora visite la URL de su host local. Ejemplo: http: // localhost: 8080 / HelloWorldServlet / HelloWorld


0

La solución que funcionó para mí es (si está usando Maven): Haga clic derecho en su proyecto, Maven -> Actualizar proyecto. Esto podría darle algún otro error con el JDK y otras bibliotecas (en mi caso, el conector MySQL), pero una vez que los arregle, ¡su problema original debería solucionarse!


0

Si desea abrir un servlet con javascript sin usar el botón 'formulario' y 'enviar', aquí está el siguiente código:

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

Llave:

1) button-id: La etiqueta 'id' que le da a su botón en su archivo html / jsp.

2) ruta-servlet-completa: la ruta que se muestra en el navegador cuando ejecuta el servlet solo


0

El mapeo en web.xml es lo que he hecho: -

  1. Si hay otro paquete creado para un nuevo programa, debemos mencionar: -

packagename.filename entre la apertura y el cierre de la etiqueta de clase de servlet en un archivo xml.

  1. Si está mapeando sus archivos en xml y no funcionan o muestran errores, entonces comente en la línea de anotación de código en los archivos respectivos.

Ambos métodos no funcionan entre sí, por lo que utilizo el método de anotación de los archivos mencionados cuando creamos el servlet o la forma de mapeo, luego elimino o comento la línea de anotación. P.ej:

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

Comentando la línea de anotación de código en el archivo respectivo, si se realiza el mapeo en xml.

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

-1

Compruebe que la raíz de contexto no puede estar vacía .

Si está utilizando eclipse:
haga clic con el botón derecho , seleccione propiedades , luego configuración del proyecto web . Compruebe que la raíz del contexto no puede estar vacía

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.