Setzen Sie die Servlet-Klasse in a package
Stellen Sie zunächst die Servlet-Klasse in Java package
. Sie sollten immer öffentlich wiederverwendbare Java - Klassen in einem Paket geschnürt, da sie sich auf Klassen unsichtbar sind , die in einem Paket sind, wie zum Beispiel des Server selbst. Auf diese Weise beseitigen Sie potenzielle umgebungsspezifische Probleme. Packletlose Servlets funktionieren nur in bestimmten Tomcat + JDK-Kombinationen, auf die man sich niemals verlassen sollte.
Bei einem "einfachen" IDE-Projekt muss die Klasse in ihrer Paketstruktur im Ordner "Java Resources" und nicht in "WebContent" abgelegt werden. Dies gilt für Webdateien wie JSP. Unten finden Sie ein Beispiel für die Ordnerstruktur eines Standard-Eclipse Dynamic-Webprojekts in der Navigatoransicht :
EclipseProjectName
|-- src
| `-- com
| `-- example
| `-- YourServlet.java
|-- WebContent
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Im Falle eines Maven-Projekts muss die Klasse in ihrer Paketstruktur platziert werden main/java
und ist daher nicht z. B. main/resources
für Dateien außerhalb der Klasse . Unten finden Sie ein Beispiel für die Ordnerstruktur eines Standard-Maven-Webanwendungsprojekts in der Navigatoransicht von Eclipse :
MavenProjectName
|-- src
| `-- main
| |-- java
| | `-- com
| | `-- example
| | `-- YourServlet.java
| |-- resources
| `-- webapp
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Beachten Sie, dass der /jsps
Unterordner nicht unbedingt erforderlich ist. Sie können sogar darauf verzichten und die JSP-Datei direkt in webcontent / webapp root ablegen, aber ich übernehme dies nur von Ihrer Frage.
Legen Sie die Servlet-URL fest url-pattern
Die Servlet-URL wird als "URL-Muster" der Servlet-Zuordnung angegeben. Es ist absolut nicht per Definition der Klassenname / Dateiname der Servlet-Klasse. Das URL-Muster ist als @WebServlet
Annotationswert anzugeben .
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.
// ...
}
Wenn Sie Pfadparameter wie unterstützen möchten /servlet/foo/bar
, verwenden Sie /servlet/*
stattdessen ein URL-Muster von . Siehe auch Servlet- und Pfadparameter wie / xyz / {value} / test, wie in web.xml zuordnen?
@WebServlet
funktioniert nur unter Servlet 3.0 oder neuer
Zur Verwendung @WebServlet
müssen Sie nur sicherstellen, dass Ihre web.xml
Datei, falls vorhanden (optional seit Servlet 3.0), als konform für Servlet 3.0+ deklariert und daher nicht konform ist, z. B. Version 2.5 oder niedriger . Unten finden Sie eine Servlet 4.0-kompatible Version (die mit Tomcat 9+, WildFly 11+, Payara 5+ usw. übereinstimmt).
<?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>
Falls Sie Servlet 3.0+ noch nicht verwenden (z. B. Tomcat 6 oder älter), entfernen Sie die @WebServlet
Anmerkung.
package com.example;
public class YourServlet extends HttpServlet {
// ...
}
Und registrieren Sie das Servlet stattdessen web.xml
wie folgt:
<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>
Beachten Sie daher, dass Sie nicht beide Möglichkeiten verwenden sollten. Verwenden Sie entweder eine annotationsbasierte Konfiguration oder eine XML-basierte Konfiguration. Wenn Sie beide haben, überschreibt die XML-basierte Konfiguration die auf Anmerkungen basierende Konfiguration.
Überprüfen des Builds / der Bereitstellung
Wenn Sie ein Build-Tool wie Eclipse und / oder Maven verwenden, müssen Sie unbedingt sicherstellen, dass sich die kompilierte Servlet-Klassendatei in ihrer Paketstruktur im /WEB-INF/classes
Ordner der erstellten WAR-Datei befindet. Im Falle von package com.example; public class YourServlet
muss es sich in befinden /WEB-INF/classes/com/example/YourServlet.class
. Andernfalls werden Sie auch im Falle @WebServlet
eines 404-Fehlers oder im Falle <servlet>
eines HTTP 500-Fehlers wie unten konfrontiert :
HTTP-Status 500
Fehler beim Instanziieren der Servlet-Klasse com.example.YourServlet
Und finden Sie im Serverprotokoll a java.lang.ClassNotFoundException: com.example.YourServlet
, gefolgt von a java.lang.NoClassDefFoundError: com.example.YourServlet
, gefolgt von javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
.
Eine einfache Möglichkeit, um zu überprüfen, ob das Servlet korrekt kompiliert und im Klassenpfad platziert wurde, besteht darin, das Build-Tool eine WAR-Datei erstellen zu lassen (z. B. Rechtsklick-Projekt, Exportieren> WAR-Datei in Eclipse) und den Inhalt dann mit einem ZIP-Tool zu überprüfen. Wenn die Servlet-Klasse in fehlt /WEB-INF/classes
oder der Export einen Fehler verursacht, ist das Projekt schlecht konfiguriert oder einige Standardeinstellungen für die IDE- / Projektkonfiguration wurden fälschlicherweise zurückgesetzt (z. B. Projekt> Automatisch erstellen wurde in Eclipse deaktiviert).
Sie müssen auch sicherstellen, dass das Projektsymbol kein rotes Kreuz aufweist, das auf einen Erstellungsfehler hinweist. Den genauen Fehler finden Sie in der Problemansicht ( Fenster> Ansicht anzeigen > Andere ... ). Normalerweise ist die Fehlermeldung in Ordnung Googlable. Wenn Sie keine Ahnung haben, starten Sie am besten von vorne und berühren Sie keine Standardeinstellungen für die IDE- / Projektkonfiguration. Falls Sie Eclipse verwenden, finden Sie Anweisungen unter Wie importiere ich die javax.servlet-API in mein Eclipse-Projekt?
Servlet einzeln testen
Vorausgesetzt, der Server localhost:8080
wird ausgeführt und die WAR wird erfolgreich in einem Kontextpfad von /contextname
(der standardmäßig den IDE-Projektnamen verwendet, Groß- und Kleinschreibung beachten!) Bereitgestellt , und das Servlet hat seine Initialisierung nicht fehlgeschlagen (Serverprotokolle für Bereitstellungen lesen /). Servlet-Erfolgs- / Fehlermeldungen und der tatsächliche Kontextpfad und die Servlet-Zuordnung), dann ist ein Servlet mit dem URL-Muster von /servlet
verfügbar http://localhost:8080/contextname/servlet
.
Sie können es einfach direkt in die Adressleiste des Browsers eingeben, um es einzeln zu testen. Wenn doGet()
es richtig überschrieben und implementiert ist, sehen Sie seine Ausgabe im Browser. Wenn Sie keine haben doGet()
oder diese falsch aufrufen super.doGet()
, wird der Fehler " HTTP 405: HTTP-Methode GET wird von dieser URL nicht unterstützt " angezeigt (der immer noch besser als eine 404 ist, da eine 405 ein Beweis dafür ist, dass das Servlet vorhanden ist selbst wird tatsächlich gefunden).
Das Überschreiben service()
ist eine schlechte Vorgehensweise, es sei denn, Sie erfinden ein MVC-Framework neu. Dies ist sehr unwahrscheinlich, wenn Sie gerade erst mit Servlets beginnen und keine Ahnung von dem in der aktuellen Frage beschriebenen Problem haben. Siehe auch Webbasierte Anwendungen von Design Patterns .
Unabhängig davon, ob das Servlet beim einzelnen Test bereits 404 zurückgibt, ist es völlig sinnlos, stattdessen ein HTML-Formular zu verwenden. Logischerweise ist es daher auch völlig sinnlos, HTML-Formulare in Fragen zu 404-Fehlern eines Servlets aufzunehmen.
Verweisen auf die Servlet-URL aus HTML
Sobald Sie überprüft haben, dass das Servlet beim einzelnen Aufruf einwandfrei funktioniert, können Sie mit HTML fortfahren. In Bezug auf Ihr konkretes Problem mit dem HTML-Formular muss der <form action>
Wert eine gültige URL sein. Gleiches gilt für <a href>
. Sie müssen verstehen, wie absolute / relative URLs funktionieren. Sie wissen, eine URL ist eine Webadresse, die Sie in der Adressleiste des Webbrowsers eingeben / sehen können. Wenn Sie eine relative URL als Formularaktion angeben, dh ohne das http://
Schema, wird sie relativ zur aktuellen URL, wie Sie in der Adressleiste Ihres Webbrowsers sehen. Es ist daher absolut nicht relativ zum Speicherort der JSP / HTML-Datei in der WAR-Ordnerstruktur des Servers, wie viele Starter zu denken scheinen.
Also, vorausgesetzt , dass die JSP - Seite mit dem HTML - Formular von geöffnet wird http://localhost:8080/contextname/jsps/page.jsp
, und Sie müssen ein Servlet in zu unterwerfen http://localhost:8080/contextname/servlet
, sind hier mehrere Fälle (beachten Sie, dass Sie sicher ersetzen können <form action>
mit <a href>
hier):
Die Formularaktion wird an eine URL mit einem führenden Schrägstrich gesendet.
<form action="/servlet">
Der führende Schrägstrich /
macht die URL relativ zur Domain, daher wird das Formular an gesendet
http://localhost:8080/servlet
Dies wird jedoch wahrscheinlich zu einem 404 führen, da er sich im falschen Kontext befindet.
Die Formularaktion wird an eine URL ohne führenden Schrägstrich gesendet.
<form action="servlet">
Dadurch wird die URL relativ zum aktuellen Ordner der aktuellen URL, sodass das Formular an gesendet wird
http://localhost:8080/contextname/jsps/servlet
Dies führt jedoch wahrscheinlich zu einem 404, da er sich im falschen Ordner befindet.
Die Formularaktion wird an eine URL gesendet, die einen Ordner höher liegt.
<form action="../servlet">
Dadurch wird ein Ordner nach oben verschoben (genau wie in den lokalen Dateisystempfaden!), Daher wird das Formular an gesendet
http://localhost:8080/contextname/servlet
Dieser muss funktionieren!
Der kanonische Ansatz besteht jedoch darin, die URL domänenbezogen zu machen, sodass Sie die URLs nicht erneut korrigieren müssen, wenn Sie die JSP-Dateien in einen anderen Ordner verschieben.
<form action="${pageContext.request.contextPath}/servlet">
Dies wird erzeugen
<form action="/contextname/servlet">
Welches wird also immer an die richtige URL senden.
Verwenden Sie in HTML gerade Anführungszeichen
Sie müssen unbedingt sicherstellen, dass Sie in HTML-Attributen wie action="..."
oder gerade Anführungszeichen verwenden action='...'
und daher keine geschweiften Anführungszeichen wie action=”...”
oder action=’...’
. Geschweifte Anführungszeichen werden in HTML nicht unterstützt und werden einfach Teil des Werts.
Siehe auch:
Andere Fälle von HTTP-Status 404-Fehler: