web-dev-qa-db-fra.com

La servlet renvoie "État HTTP 404 La ressource demandée (/ servlet) n'est pas disponible"

J'ai un formulaire HTML dans un fichier JSP dans mon dossier WebContent/jsps. J'ai une classe de servlet servlet.Java dans mon paquet par défaut dans le dossier src. Dans mon web.xml, il est mappé en tant que /servlet.

J'ai essayé plusieurs URL dans l'attribut action du formulaire HTML:

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

Mais aucun de ces travaux. Ils continuent tous à renvoyer une erreur HTTP 404 comme ci-dessous dans Tomcat 6/7/8:

Statut HTTP 404 -/servlet

Description : La ressource demandée (/ servlet) n'est pas disponible.

Ou comme ci-dessous dans Tomcat 8.5/9:

Statut HTTP 404 - Introuvable

Message :/servlet

Description : Le serveur d'origine n'a pas trouvé de représentation actuelle de la ressource cible ou n'est pas disposé à divulguer celle qui existe.

Pourquoi ça ne marche pas? 

70
pongahead

Placez la classe de servlet dans un package

Tout d'abord, placez la classe de servlet dans un Java package. Vous devez toujours placer publiquement les classes Java réutilisables dans un package, sinon elles sont invisibles pour les classes contenues dans un package, tel que le serveur lui-même. De cette façon, vous éliminez les problèmes potentiels spécifiques à l'environnement. Les servlets sans emballage ne fonctionnent que dans certaines combinaisons Tomcat + JDK et il ne faut jamais s'y fier.

Dans le cas d'un projet "simple" IDE, la classe doit être placée dans sa structure de package dans le dossier "Java Resources" et, par conséquent, not ​​"WebContent", ceci est destiné au Web. des fichiers tels que JSP. Vous trouverez ci-dessous un exemple de la structure de dossier d’un Eclipse par défaut Projet Web dynamique, comme indiqué dans Navigateur:

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

Dans le cas d'un projet Maven, la classe doit être placée dans sa structure de package dans main/Javaet ainsi not ​​p. Ex. main/resources, c'est pour les fichiers non-classe . Vous trouverez ci-dessous un exemple de la structure de dossier d'un projet d'application Web Maven par défaut, telle que vue dans la vue Navigator d'Eclipse:

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

Notez que le sous-dossier /jsps n’est pas strictement nécessaire. Vous pouvez même vous en passer et placer le fichier JSP directement dans webcontent/webapp root, mais je ne fais que reprendre cela de votre question.

Définir l'URL du servlet dans url-pattern

L'URL du servlet est spécifié en tant que "modèle d'URL" du mappage du servlet. Ce n'est absolument pas, par définition, le nom de classe/nom de fichier de la classe servlet. Le modèle d'URL doit être spécifié avec la valeur de l'annotation @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.
    // ...
}

Si vous souhaitez prendre en charge des paramètres de chemin tels que /servlet/foo/bar, utilisez un modèle d'URL de /servlet/* à la place. Voir aussi Les paramètres de servlet et de chemin comme/xyz/{valeur}/test, comment mapper dans web.xml?

@WebServlet ne fonctionne que sur Servlet 3.0 ou plus récent

Pour utiliser @WebServlet, vous devez simplement vous assurer que votre fichier web.xml, le cas échéant (il est facultatif depuis Servlet 3.0), est déclaré conforme à la version Servlet 3.0+ et donc pas conforme par exemple Version 2.5 ou inférieure . Vous trouverez ci-dessous un serveur compatible avec Servlet 3.1 (qui correspond aux 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>

Ou, si vous n'êtes pas encore sur Servlet 3.0+ (pas avec Tomcat 7 ou une version plus récente, mais avec Tomcat 6 ou une version plus ancienne), supprimez l'annotation @WebServlet.

package com.example;

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

Et enregistrez la servlet à la place dans web.xml comme ceci:

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

Notez donc que vous ne devez pas utiliser les deux méthodes. Utilisez une configuration basée sur une annotation ou une configuration basée sur XML. Lorsque vous avez les deux, la configuration basée sur XML remplace la configuration basée sur les annotations.

Vérification de la construction/du déploiement

Si vous utilisez un outil de construction tel que Eclipse et/ou Maven, vous devez vous assurer absolument que le fichier de classe du servlet compilé réside dans sa structure de package dans le dossier /WEB-INF/classes du fichier WAR produit. Dans le cas de package com.example; public class YourServlet, il doit être situé dans /WEB-INF/classes/com/example/YourServlet.class. Sinon, vous rencontrerez dans le cas de @WebServlet également une erreur 404, ou dans le cas de <servlet> une erreur HTTP 500 comme ci-dessous:

Statut HTTP 500

Erreur lors de l'instanciation de la classe de servlet com.example.YourServlet

Et trouvez dans le journal du serveur un Java.lang.ClassNotFoundException: com.example.YourServlet, suivi d'un Java.lang.NoClassDefFoundError: com.example.YourServlet, suivi de javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet.

Un moyen facile de vérifier si le servlet est correctement compilé et placé dans classpath consiste à laisser l’outil de construction générer un fichier WAR (par exemple, projet rightclick, Exporter> fichier WAR dans Eclipse), puis inspecter son contenu avec un outil Zip. Si la classe de servlet est manquante dans /WEB-INF/classes, le projet est mal configuré ou certaines valeurs par défaut de la configuration du projet/IDE ont été annulées par erreur (par exemple, Projet> Construire automatiquement ​​a été désactivé dans Eclipse). Si vous n'avez pas la moindre idée, le mieux est de redémarrer à partir de zéro et de ne pas toucher aux valeurs par défaut de la configuration du projet ou de l'IDE.

Tester le servlet individuellement

Sous réserve que le serveur s'exécute sur localhost:8080 et que le fichier WAR soit correctement déployé sur un chemin de contexte de /contextname (le nom de projet IDE étant sensible à la casse!), Et le servlet n'a pas échoué à son initialisation (lisez les journaux du serveur pour tous les messages de déploiement/servlet et le chemin de contexte réel et le mappage de servlet), puis un servlet avec un modèle d'URL de /servlet est disponible à http://localhost:8080/contextname/servlet.

Vous pouvez simplement le saisir directement dans la barre d'adresse de votre navigateur pour le tester individuellement. Si sa doGet() est correctement remplacée et implémentée, vous verrez sa sortie dans le navigateur. Ou si vous n'avez pas de doGet() ou s'il appelle incorrectement super.doGet(), un " HTTP 405: la méthode HTTP GET n'est pas prise en charge par cette URL "une erreur sera affichée (ce qui est toujours préférable à un 404 car un 405 est la preuve que le servlet lui-même est réellement trouvé).

Remplacer service() est une mauvaise pratique, sauf si vous réinventez le framework MVC - ce qui est très improbable si vous débutez avec des servlets et que vous n'avez aucune idée du problème décrit dans la question actuelle;) Voir aussi Applications Web basées sur les modèles de conception .

Quoi qu'il en soit, si la servlet retourne déjà 404 lorsqu'elle est testée individuellement, il est alors totalement inutile d'essayer avec un formulaire HTML. Logiquement, il est donc également inutile d'inclure un formulaire HTML dans les questions sur les erreurs 404 provenant d'un servlet.

Référencer l'URL du servlet à partir de HTML

Une fois que vous avez vérifié que le servlet fonctionne correctement lorsqu'il est appelé individuellement, vous pouvez passer au format HTML. En ce qui concerne votre problème concret avec le formulaire HTML, la valeur <form action> doit être une URL valide. La même chose s'applique à <a href>. Vous devez comprendre le fonctionnement des URL absolues/relatives. Vous savez, une URL est une adresse Web que vous pouvez entrer/voir dans la barre d'adresse du navigateur Web. Si vous spécifiez une URL relative en tant qu'action de formulaire, c'est-à-dire sans le schéma http://, elle devient alors relative à l'URL actuelle comme vous le voyez dans la barre d'adresse de votre navigateur Web. Cela n’est donc absolument pas relatif à l’emplacement du fichier JSP/HTML dans la structure de dossiers WAR du serveur, comme le pensent beaucoup d’entre eux.

Donc, en supposant que la page JSP avec le formulaire HTML soit ouverte par http://localhost:8080/contextname/jsps/page.jsp et que vous deviez la soumettre à un servlet situé dans http://localhost:8080/contextname/servlet, voici plusieurs cas (notez que vous pouvez remplacer en toute sécurité <form action> avec <a href> ici):

  • L'action de formulaire est soumise à une URL avec une barre oblique.

    <form action="/servlet">
    

    La barre oblique / place l'URL par rapport au domaine. Le formulaire est donc soumis à

    http://localhost:8080/servlet
    

    Mais cela aboutira probablement à un 404 car il se trouve dans le mauvais contexte.


  • L'action de formulaire est soumise à une URL sans barre oblique.

    <form action="servlet">
    

    Cela rend l'URL par rapport au dossier actuel de l'URL actuelle, ainsi le formulaire sera soumis à

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

    Mais cela entraînera probablement un 404 car il se trouve dans le mauvais dossier.


  • L'action de formulaire est soumise à une URL qui monte d'un dossier.

    <form action="../servlet">
    

    Cela créera un dossier (exactement comme dans les chemins du système de fichiers du disque local), ainsi le formulaire sera soumis à

    http://localhost:8080/contextname/servlet
    

    Celui-ci doit fonctionner!


  • Cependant, l'approche canonique consiste à rendre l'URL relative au domaine de sorte que vous n'ayez pas besoin de redéfinir les URL lorsque vous déplacez les fichiers JSP dans un autre dossier.

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

    Cela va générer

    <form action="/contextname/servlet">
    

    Ce qui sera donc toujours soumis à la bonne URL.


Utilisez des guillemets droits en HTML

Vous devez absolument vous assurer que vous utilisez des guillemets droits dans les attributs HTML tels que action="..." ou action='...' et donc pas guillemets bouclés tels que action=”...” ou action=’...’. Les guillemets bouclés ne sont pas pris en charge en HTML et ils feront simplement partie de la valeur.

Voir également:

Autres cas d'erreur HTTP Status 404:

112
BalusC

Scénario n ° 1: Vous avez accidentellement redéployé à partir de la ligne de commande alors que Tomcat exécutait déjà l'exécution de.

Réponse courte: Arrêtez Tomcat, supprimez le dossier cible, package mvn, puis redéployez


Scénario 2: request.getRequestDispatcher ("MIS_SPELLED_FILE_NAME .jsp")

Réponse courte: Vérifiez le nom du fichier orthographe, assurez-vous que case est correct.


Scénario n ° 3: exceptions non trouvées dans la classe (Répondez ici parce que: question # 17982240) ( Java.lang.ClassNotFoundException pour une servlet dans Tomcat avec Eclipse ) (Était marqué comme duplicata et m'a dirigé ici)

Réponse courte n ° 3.1: le fichier web.xml contient un chemin de package incorrect dans la balise servlet-class.

Réponse courte n ° 3.2: Le fichier Java a une déclaration d'importation incorrecte.


Vous trouverez ci-dessous d'autres détails concernant le scénario n ° 1:


1: Stop Tomcat

  • Option 1: via CTRL + C dans le terminal.
  • Option 2: (terminal fermé alors que Tomcat est toujours en cours d'exécution)
  • ------------ 2.1: appuyez sur: Windows + R -> tapez: "services.msc"
  • ------------ 2.2: Recherchez "Apache Tomcat #. # Tomcat #" dans la colonne Nom de la liste.
  • ------------ 2.3: Clic droit -> "stop"

2: Supprimez le dossier "cible" .(mvn clean ne vous aidera pas ici)

3: paquet mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE _

(Mine: Java -jar cible/dependency/webapp-runner.jar --port 5190 cible/*. War)

Full Back Story:


Accidentellement, ouvrit une nouvelle fenêtre git-bash et Tenta de déployer un fichier .war pour mon projet heroku via:

Java -jar cible/dependency/webapp-runner.jar --port 5190 cible/*. War

Après un échec de déploiement, j'ai réalisé que deux fenêtres git-bash étaient ouvertes: .__ et n'avaient pas utilisé CTLR + C pour arrêter le déploiement précédent.

J'ai été rencontré:

Statut HTTP 404 - Type introuvable Rapport de statut

Message /if-student-test.jsp

Description Le serveur d'origine n'a pas trouvé de représentation actuelle pour la ressource cible ou n'est pas disposé à divulguer celui-ci existe.

Apache Tomcat/8.5.31

Vous trouverez ci-dessous d'autres détails concernant le scénario 3:


SCÉNARIO 3.1: Le chemin du package servlet-class est incorrect dans votre fichier web.xml.

Il devrait correspondre à l'instruction de package en haut de votre classe de servlet Java.

Fichier: my_stuff/MyClass.Java:

   package my_stuff;

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

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

SCÉNARIO 3.2:

Vous avez mis la mauvaise déclaration "package" en haut de votre fichier myClass.Java.

Par exemple:

Le fichier est dans le dossier "/ my_stuff"

Vous écrivez par erreur:

package com.my_stuff

C'est délicat parce que:

1: Le build maven (paquet mvn) ne signalera aucune erreur ici.

2: la ligne de classe servlet dans web.xml peut avoir le chemin du paquet CORRECT. Par exemple:

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

Pile utilisée: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10:

1
J.M.I. MADISON

Solution pour HTTP Status 404 dans l'EDI NetBeans: Cliquez avec le bouton droit de la souris sur votre projet et accédez à ses propriétés, puis cliquez sur Exécuter, puis entrez l'URL relative de votre projet comme index.jsp.

  1. Projet-> Propriétés
  2. Cliquez sur Exécuter
  3. URL relative: /index.jsp (sélectionnez l'URL racine de votre projet)

enter image description here

0
O R Imon

Mon problème était qu'il manquait l'annotation @RequestBody à ma méthode. Après avoir ajouté l'annotation, je n'ai plus reçu l'exception 404.

0
THE_DOM

Un vieux fil, mais comme je ne l'ai pas trouvé ailleurs, voici une autre possibilité:

Si vous utilisez servlet-api 3.0 + , votre fichier web.xml doit PAS include metadata-complete="true" attribut

enter image description here

Ceci indique à Tomcat de mapper les servlets en utilisant les données fournies dans web.xml au lieu d'utiliser l'annotation @WebServlet.

0
Chaitanya Bhardwaj

Faites les deux étapes suivantes. J'espère que le problème "404 non trouvés" sur le serveur Tomcat sera résolu lors du développement de l'application de servlet Java.

Étape 1: Right click on the server(in the server Explorer tab)->Properties->Switch Location from workspace metadata to Tomcat server

Étape 2: Double Click on the server(in the server Explorer tab)->Select Use Tomcat installation option inside server location menu

0
Sajal Saha

J'ai supprimé l'ancienne bibliothèque Web, telles que les bibliothèques de framework Spring. Et construisez un nouveau chemin des bibliothèques. Alors ça marche.

0
pajarnas