html - sessions - El servlet devuelve "HTTP Status 404 El recurso solicitado(/ servlet) no está disponible"
jsp sessions (3)
Tengo un formulario HTML en un archivo JSP en mi carpeta WebContent/jsps
. Tengo una clase servlet servlet.java
en mi paquete predeterminado en la carpeta src
. En mi web.xml
, se mapea como /servlet
.
He intentado varias URL en action
atributo 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 continúan devolviendo un error HTTP 404 como el siguiente en Tomcat 6/7/8:
HTTP Status 404 - / servlet
Descripción : el recurso solicitado (/ servlet) no está disponible.
O como se detalla a continuación en Tomcat 8.5 / 9:
HTTP Status 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 está funcionando?
Poner clase de servlet en un package
En primer lugar, coloque la clase de servlet en un package
Java. Siempre debe colocar clases de Java públicamente reutilizables en un paquete, de lo contrario, son invisibles para las clases que están en un paquete, como el servidor en sí. De esta forma, elimina posibles problemas específicos del entorno. Los servlets sin paquete solo funcionan 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 de Java" y, por lo tanto, no es "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 predeterminado de Eclipse , 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 de main/java
y, por lo tanto, no por ejemplo main/resources
, esto es para archivos que no sean de clase . A continuación se muestra un ejemplo de la estructura de carpetas de un proyecto de aplicación de 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 subcarpeta /jsps
no es estrictamente necesaria. Incluso puedes prescindir de él y poner el archivo JSP directamente en webcontent / webapp root, pero solo estoy tomando esto de tu pregunta.
Establecer URL de servlet en url-pattern
La URL del servlet se especifica como el "patrón de URL" de la asignación del servlet. Definitivamente no es por definición el nombre de clase / nombre de archivo de la clase de servlet. El patrón de URL se debe especificar como valor de la anotación @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.
// ...
}
En caso de que desee admitir parámetros de ruta como /servlet/foo/bar
, utilice en su lugar un patrón de URL de /servlet/*
. Consulte también Parámetros de servlet y ruta como / xyz / {value} / test, cómo mapear en web.xml?
@WebServlet
funciona solo en Servlet 3.0 o posterior
Para usar @WebServlet
, solo necesita asegurarse de que su archivo web.xml
, si lo hay (es opcional desde Servlet 3.0), se declare conforme a la versión Servlet 3.0+ y, por lo tanto, no conforme, por ejemplo, versión 2.5 o inferior . A continuación se muestra una compatible con Servlet 3.1 (que coincide con Tomcat 8+, WildFly 8+, GlassFish 4+, etc.).
<?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>
O, en caso de que aún no tenga Servlet 3.0+ (no Tomcat 7 o posterior, pero Tomcat 6 o anterior), elimine la anotación @WebServlet
.
package com.example;
public class YourServlet extends HttpServlet {
// ...
}
Y registre el servlet en su lugar en web.xml
siguiente manera:
<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>
Tenga en cuenta que no debe usar ambas formas. Utilice la configuración basada en anotaciones o la configuración basada en XML. Cuando tenga ambos, la configuración basada en XML anulará la configuración basada en anotaciones.
Verificando la compilación / implementación
En caso de que esté utilizando una herramienta de compilación como Eclipse y / o Maven, entonces debe asegurarse de que el archivo de clase de servlet compilado resida en su estructura de paquete en la carpeta /WEB-INF/classes
del archivo WAR producido. En caso de package com.example; public class YourServlet
package com.example; public class YourServlet
, debe estar ubicado en /WEB-INF/classes/com/example/YourServlet.class
. De lo contrario, se encontrará en el caso de que @WebServlet
también sea un error 404, o en el caso de <servlet>
un error HTTP 500 como el siguiente:
Estado HTTP 500
Error al instanciar la clase servlet com.example.YourServlet
Y encuentre en el registro del servidor una java.lang.ClassNotFoundException: com.example.YourServlet
, seguido de un java.lang.NoClassDefFoundError: com.example.YourServlet
, a su vez seguido de javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
.
Una manera fácil de verificar si el servlet está compilado y ubicado correctamente en classpath es permitir que la herramienta genere un archivo WAR (por ejemplo, haga clic derecho en el proyecto, Exportar> archivo WAR en Eclipse) y luego inspeccione su contenido con una herramienta ZIP. Si falta la clase de servlet en /WEB-INF/classes
, entonces el proyecto está mal configurado o algunos valores predeterminados de configuración IDE / proyecto se han revertido erróneamente (por ejemplo, Project> Build Automatically se ha desactivado en Eclipse). En caso de que no tenga idea, lo mejor es reiniciar desde cero y no tocar ningún valor predeterminado de configuración IDE / proyecto.
Probando el servlet individualmente
Siempre que el servidor se ejecute en localhost:8080
, y que el WAR se despliegue correctamente en una ruta de contexto de /contextname
(que por defecto es el nombre del proyecto IDE, ¡ /contextname
mayúsculas y minúsculas!) Y el servlet no haya fallado su inicialización (leer servidor registros para cualquier mensaje de éxito / falla de despliegue / servlet y la ruta de contexto real y la asignación de servlet), luego un servlet con patrón de URL de /servlet
está disponible en http://localhost:8080/contextname/servlet
.
Puede simplemente ingresarlo directamente en la barra de direcciones del navegador para probarlo de manera involuntaria. Si doGet()
se sobrescribe e implementa correctamente, verá su resultado en el navegador. O si no tiene ningún doGet()
o si llama incorrectamente a super.doGet()
, entonces se mostrará un error " HTTP 405: HTTP método GET no es compatible con esta URL " (que es aún mejor que un 404 como un 405 es evidencia de que el servlet sí mismo se encuentra realmente).
El service()
Overriding service()
es una mala práctica, a menos que esté reinventando un framework MVC, lo cual es muy poco probable si recién está comenzando con servlets y no tiene idea del problema descrito en la pregunta actual; vea también Design Patterns web aplicaciones basadas
De todos modos, si el servlet ya devuelve 404 cuando se prueba de forma involuntaria, entonces no tiene sentido probar con un formulario HTML. Lógicamente, por lo tanto, es completamente inútil incluir cualquier 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 correctamente cuando se lo invoca individualmente, puede avanzar a HTML. En cuanto a su problema concreto con el formulario HTML, el valor <form action>
debe ser una URL válida. Lo mismo aplica para <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 esquema http://
, se convierte en relativa a la URL actual como se ve en la barra de direcciones de su navegador web. Por lo tanto, no es absolutamente relativo a la ubicación del archivo JSP / HTML en la estructura de la carpeta WAR del servidor, como muchos principiantes parecen pensar.
Entonces, suponiendo que la página JSP con el formulario HTML esté abierta por http://localhost:8080/contextname/jsps/page.jsp
, y debe enviarla a un servlet ubicado en http://localhost:8080/contextname/servlet
, aquí hay varios casos (tenga en cuenta que puede sustituir de <form action>
segura <form action>
con <a href>
aquí):
La acción de formulario se envía a una URL con una barra diagonal.
<form action="/servlet">
La barra diagonal
/
hace que la URL sea relativa al dominio, por lo que el formulario se enviará ahttp://localhost:8080/servlet
Pero esto probablemente dará como resultado un 404 ya que está en el contexto incorrecto.
La acción del formulario se envía a una URL sin una barra diagonal.
<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 dará como resultado 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 irá una carpeta hacia arriba (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 el URL sea relativo al dominio para que no tenga que arreglar 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">
Que siempre se enviará a la URL correcta.
Use citas rectas en HTML
Debes estar absolutamente seguro de que estás utilizando comillas simples en atributos HTML como action="..."
o action=''...''
y por lo tanto no hay comillas rizadas como action=”...”
o action=''...''
. Las comillas cursivas no son compatibles con HTML y simplemente se convertirán en parte del valor.
Ver también:
- Nuestra página wiki servlets - Contiene algunos ejemplos de hello world
- Cómo llamar a la clase servlet desde el formulario HTML
- doGet y doPost en Servlets
- ¿Cómo paso el elemento actual al método de Java haciendo clic en un hipervínculo o botón en la página JSP?
Otros casos de error de HTTP Status 404:
- HTTP Status 404 - El servlet [ServletName] no está disponible
- HTTP Status 404 - El recurso solicitado (/ ProjectName /) no está disponible
- Estado HTTP 404 - El recurso solicitado (/) no está disponible
- JSP in / WEB-INF devuelve "HTTP Status 404 El recurso solicitado no está disponible"
- Hacer referencia a un recurso colocado en la carpeta WEB-INF en el archivo JSP devuelve HTTP 404 en el recurso
- El navegador no puede acceder / encontrar recursos relativos como CSS, imágenes y enlaces cuando llama a un servlet que lo reenvía a un JSP
Solución para HTTP Status 404
en NetBeans IDE: Haga clic con el botón derecho en su proyecto y vaya a las propiedades de su proyecto, luego haga clic en ejecutar, luego ingrese su URL relativa al proyecto como index.jsp
.
- Proyecto-> Propiedades
- Haga clic en Ejecutar
- URL relativa: /index.jsp (Seleccione la URL raíz de su proyecto)
Escenario: Has vuelto a implementar de forma accidental desde la línea de comandos mientras Tomcat ya se estaba ejecutando .
Respuesta corta: Detenga Tomcat, elimine la carpeta de destino , el paquete mvn, luego vuelva a implementar
1: Stop Tomcat
- Opción 1: a través de 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: Encuentra "Apache Tomcat #. # Tomcat #" en la columna Nombre de la lista.
- ------------ 2.3: Click derecho -> " parar "
2: elimine la carpeta "objetivo". (mvn clean no te ayudará aquí)
3: paquete mvn
4: YOUR_DEPLOYMENT_COMMAND_HERE
(Mina: java -jar target / dependency / webapp-runner.jar --port 5190 target / *. War)
Historia Completa:
Accidentially abrió 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 al implementar, 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:
HTTP Status 404 - No encontrado Tipo Informe de estado
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
Pila utilizada: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10 :