Le servlet renvoie «HTTP Status 404 La ressource demandée (/ servlet) n'est pas disponible»


95

J'ai un formulaire HTML dans un fichier JSP dans mon WebContent/jspsdossier. J'ai une classe de servlet servlet.javadans mon package par défaut dans le srcdossier. Dans mon web.xmlil est mappé comme /servlet.

J'ai essayé plusieurs URL en actionattribut du formulaire HTML:

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

Mais rien de tout cela ne fonctionne. Ils continuent tous de renvoyer une erreur HTTP 404 comme ci-dessous dans Tomcat 6/7/8:

État HTTP 404 - / servlet

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

Ou comme ci-dessous dans Tomcat 8.5 / 9:

État HTTP 404 - introuvable

Message : / servlet

Description : le serveur d'origine n'a pas trouvé de représentation actuelle pour la ressource cible ou n'est pas disposé à révéler qu'il en existe une

Pourquoi ça ne marche pas?

Réponses:


127

Placez la classe de servlet dans un package

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

Dans le cas d'un projet IDE "simple", la classe doit être placée dans sa structure de package dans le dossier "Java Resources" et donc pas "WebContent", c'est pour les fichiers Web tels que JSP. Vous trouverez ci-dessous un exemple de la structure de dossiers d'un projet Web dynamique Eclipse par défaut, comme indiqué dans la vue 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 à l'intérieur main/java et donc pas par exemple main/resources, c'est pour les fichiers non-classe . Vous trouverez ci-dessous un exemple de la structure de dossiers d'un projet Webapp Maven par défaut, comme illustré dans la vue Navigateur d'Eclipse :

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

Notez que le /jspssous-dossier n'est pas strictement nécessaire. Vous pouvez même vous en passer et placer le fichier JSP directement dans la racine webcontent / webapp, mais je reprends simplement cela à partir de votre question.

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

L'URL du servlet est spécifiée comme "modèle d'URL" du mappage de servlet. Ce n'est absolument pas par définition le nom de classe / nom de fichier de la classe de servlet. Le modèle d'URL doit être spécifié comme valeur d' @WebServletannotation.

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 /servlet/*plutôt un modèle d'URL . Voir aussi Servlet et paramètres de chemin comme / xyz / {value} / test, comment mapper dans web.xml?

@WebServlet fonctionne uniquement sur Servlet 3.0 ou plus récent

Pour l'utiliser @WebServlet, vous devez seulement vous assurer que votre web.xmlfichier, le cas échéant (il est facultatif depuis Servlet 3.0), est déclaré conforme à la version Servlet 3.0+ et donc non conforme, par exemple la version 2.5 ou inférieure . Vous trouverez ci-dessous un compatible Servlet 4.0 (qui correspond à 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>

Ou, si vous n'êtes pas encore sur Servlet 3.0+ (par exemple Tomcat 6 ou plus ancien), supprimez l' @WebServletannotation.

package com.example;

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

Et enregistrez le servlet à la place web.xmlcomme 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 des annotations 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 qu'Eclipse et / ou Maven, vous devez vous assurer absolument que le fichier de classe de servlet compilé réside dans sa structure de package dans le /WEB-INF/classesdossier 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 serez confronté en cas d' @WebServleterreur 404 ou en cas d' <servlet>erreur HTTP 500 comme ci-dessous:

État HTTP 500

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

Et trouvez dans le journal du serveur a java.lang.ClassNotFoundException: com.example.YourServlet, suivi de a java.lang.NoClassDefFoundError: com.example.YourServlet, à son tour suivi de javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet.

Un moyen simple de vérifier si le servlet est correctement compilé et placé dans classpath est de laisser l'outil de construction produire un fichier WAR (par exemple, cliquez avec le bouton droit sur le projet, Exporter> Fichier WAR dans Eclipse) et ensuite inspecter son contenu avec un outil ZIP. Si la classe de servlet est manquante dans /WEB-INF/classes, ou si l'exportation provoque une erreur, le projet est mal configuré ou certaines valeurs par défaut de configuration IDE / projet ont été rétablies par erreur (par exemple, Projet> Construire automatiquement a été désactivé dans Eclipse).

Vous devez également vous assurer que l'icône du projet n'a pas de croix rouge indiquant une erreur de construction. Vous pouvez trouver l'erreur exacte dans la vue Problèmes ( Fenêtre> Afficher la vue> Autre ... ). Habituellement, le message d'erreur est bien Googlable. Dans le cas où vous n'avez aucune idée, le mieux est de redémarrer à partir de zéro et de ne pas toucher aux valeurs par défaut de configuration IDE / projet. Si vous utilisez Eclipse, vous pouvez trouver des instructions dans Comment importer l'API javax.servlet dans mon projet Eclipse?

Tester le servlet individuellement

À condition que le serveur s'exécute localhost:8080et que le WAR soit déployé avec succès sur un chemin de contexte de /contextname(qui par défaut est le nom du projet IDE, sensible à la casse!), Et que le servlet n'a pas échoué son initialisation (lire les journaux du serveur pour tout déploiement / les messages de réussite / échec du servlet et le chemin de contexte réel et le mappage de servlet), puis un servlet avec un modèle d'URL /servletest disponible sur http://localhost:8080/contextname/servlet.

Vous pouvez simplement le saisir directement dans la barre d'adresse du navigateur pour le tester de manière individuelle. S'il doGet()est correctement remplacé et implémenté, vous verrez sa sortie dans le navigateur. Ou si vous n'en avez pas doGet()ou s'il appelle incorrectement super.doGet(), une erreur " HTTP 405: Méthode HTTP GET n'est pas prise en charge par cette URL " sera affichée (ce qui est toujours mieux qu'un 404 car un 405 est la preuve que le servlet se trouve réellement).

Le remplacement service()est une mauvaise pratique, à moins que vous ne réinventiez un framework MVC - ce qui est très peu probable 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 les applications Web Design Patterns .

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

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

Une fois que vous avez vérifié que le servlet fonctionne correctement lorsqu'il est appelé individuellement, vous pouvez passer au HTML. Quant à votre problème concret avec le formulaire HTML, la <form action>valeur 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 comme vous pouvez la saisir / la voir dans la barre d'adresse du navigateur Web. Si vous spécifiez une URL relative comme action de formulaire, c'est-à-dire sans le http://schéma, elle devient relative à l' URL actuelle comme vous le voyez dans la barre d'adresse de votre navigateur Web. Ce n'est donc absolument pas relatif à l'emplacement du fichier JSP / HTML dans la structure des dossiers WAR du serveur comme de nombreux débutants semblent le penser.

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

  • L'action de formulaire se soumet à une URL avec une barre oblique en tête.

    <form action="/servlet">

    La barre oblique principale /rend l'URL relative au domaine, ainsi le formulaire sera soumis à

    http://localhost:8080/servlet

    Mais cela entraînera probablement un 404 car il est dans le mauvais contexte.


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

    <form action="servlet">

    Cela rend l'URL relative 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 se soumet à une URL qui monte d'un dossier.

    <form action="../servlet">

    Cela ira d'un dossier vers le haut (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!


  • L'approche canonique, cependant, consiste à rendre l'URL relative au domaine afin que vous n'ayez pas besoin de réparer les URL à nouveau lorsque vous déplacez les fichiers JSP dans un autre dossier.

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

    Cela générera

    <form action="/contextname/servlet">

    Lequel se soumettra donc toujours à la bonne URL.


Utilisez des guillemets droits en HTML

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

Voir également:

Autres cas d'erreur HTTP Status 404:


1
version web-app = "3.1" en utilisant glassfish, je pourrais tester mon servlet individuellement très bien quand j'avais un mappage dans web.xml ET l'annotation. J'ai supprimé le mappage et laissé l'annotation puisque j'ai la dernière version, mais j'obtiendrais alors une erreur 404?
SallyRothroat

1
Cela peut se produire si vous incluez des bibliothèques de servlet 2.5 ou plus anciennes dans l'application Web elle-même au lieu de compter sur l'environnement d'exécution cible pour fournir les bibliothèques de servlet par lui-même.
BalusC

@xdola: C'est en effet fragile car cela dépend de l'URI de la requête. Lisez simplement la réponse pour l'explication de votre problème et quelle est la bonne approche.
BalusC

4

Scénario n ° 1: vous avez accidentellement redéployé à partir de la ligne de commande alors que tomcat était déjà en cours d'exécution .

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


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

Réponse courte: Vérifiez l' orthographe du nom de fichier , assurez-vous que la casse est correcte.


Scénario n ° 3: Exceptions de classe non trouvée (réponse mise ici car: Question n ° 17982240) ( java.lang.ClassNotFoundException pour servlet dans tomcat avec eclipse ) (a été marqué comme dupliqué et m'a dirigé ici)

Réponse courte n ° 3.1: web.xml a un chemin de package incorrect dans la balise de classe servlet.

Réponse courte n ° 3.2: le fichier java a une mauvaise déclaration d'importation.


Vous trouverez ci-dessous plus de détails pour le scénario n ° 1:


1: Arrêtez 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 -> " arrêter "

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

3: paquet mvn

4: VOTRE_DEPLOIEMENT_COMMAND_HERE

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

Histoire complète:


J'ai accidentellement ouvert une nouvelle fenêtre git-bash et essayé de déployer un fichier .war pour mon projet heroku via:

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

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

J'ai été rencontré:

État HTTP 404 - Rapport d'état de type introuvable

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é à révéler qu'il en existe une.

Apache Tomcat / 8.5.31

Vous trouverez ci-dessous plus de détails pour le scénario n ° 3:


SCÉNARIO 3.1: Le chemin du package de la classe servlet est incorrect dans votre fichier web.xml.

Il doit correspondre à l'instruction 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 se trouve dans le dossier " / my_stuff "

Vous écrivez par erreur:

package com.my_stuff

C'est délicat car:

1: Le build maven (package mvn) ne rapportera aucune erreur ici.

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

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

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


Votre AppName.war et donc le nom de dossier éclaté ne correspondent pas à votre nom attendu, par exemple lorsque votre fichier war est versionné comme AppName-1.0-SNAPSHOT.war et que vous essayez / AppName /.
jla

0

Solution pour HTTP Status 404NetBeans IDE: Faites un clic droit sur votre projet et accédez aux propriétés de votre projet, puis cliquez sur Exécuter, puis saisissez l'URL relative de votre projet comme index.jsp.

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

entrez la description de l'image ici


0

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


0

Suivez les deux étapes suivantes. J'espère que cela résoudra le problème "404 non trouvé" dans le serveur tomcat pendant le 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

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


0

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

Si vous utilisez servlet-api 3.0+ , votre web.xml ne doit PAS inclure d' metadata-complete="true"attribut

entrez la description de l'image ici

Cela indique à tomcat de mapper les servlets en utilisant les données fournies dans web.xmlau lieu d'utiliser l' @WebServletannotation.


0

Tout d'abord, exécutez votre IDE en tant qu'administrateur. Après cela, cliquez avec le bouton droit sur le dossier du projet -> Facettes du projet et assurez-vous que la version Java est définie correctement. Sur mon PC. (Par exemple 1.8) Maintenant, cela devrait fonctionner.

Ne démarrez pas simplement votre serveur, par exemple Wildfly, en utilisant le cmd. Il doit être lancé dans l'EDI et maintenant visiter votre URL localhost. Exemple: http: // localhost: 8080 / HelloWorldServlet / HelloWorld


0

Le correctif qui a fonctionné pour moi est (si vous utilisez Maven): Cliquez avec le bouton droit sur votre projet, Maven -> Mettre à jour le projet. Cela pourrait vous donner une autre erreur avec le JDK et d'autres bibliothèques (dans mon cas, le connecteur MySQL), mais une fois que vous les avez résolus, votre problème d'origine devrait être corrigé!


0

Si vous souhaitez ouvrir un servlet avec javascript sans utiliser les boutons 'formulaire' et 'soumettre', voici le code suivant:

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

Clé:

1) button-id: La balise 'id' que vous donnez à votre bouton dans votre fichier html / jsp.

2) full-servlet-path: le chemin qui s'affiche dans le navigateur lorsque vous exécutez le servlet seul


0

La cartographie en web.xml est ce que j'ai fait: -

  1. S'il y a un autre paquet fait pour un nouveau programme, nous devons mentionner: -

packagename.filename entre l'ouverture et la fermeture de la balise de classe servlet dans le fichier xml.

  1. Si vous mappez vos fichiers au format XML et qu'ils ne fonctionnent pas ou affichent des erreurs, commentez la ligne d'annotation du code dans les fichiers respectifs.

Les deux méthodes ne fonctionnent pas l'une avec l'autre, donc j'utilise la méthode d'annotation des fichiers mentionnés lorsque nous créons le servlet ou la méthode de mappage, puis je supprime ou commente la ligne d'annotation. Par exemple:

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

Commenter la ligne d'annotation du code dans le fichier respectif, si le mappage en xml est effectué.

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

-1

Veuillez vérifier que la racine du contexte ne peut pas être vide .

Si vous utilisez eclipse: faites
un clic droit , sélectionnez les propriétés , puis les paramètres du projet Web . Vérifiez que la racine de contexte ne peut pas être vide

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.