Metti la classe servlet in un file package
Prima di tutto, metti la classe servlet in un Java package
. Dovresti sempre inserire le classi Java pubblicamente riutilizzabili in un pacchetto, altrimenti sono invisibili alle classi che si trovano in un pacchetto, come il server stesso. In questo modo si eliminano potenziali problemi specifici dell'ambiente. I servlet senza pacchetto funzionano solo in specifiche combinazioni Tomcat + JDK e su questo non si dovrebbe mai fare affidamento.
In caso di un progetto IDE "semplice", la classe deve essere collocata nella sua struttura del pacchetto all'interno della cartella "Java Resources" e quindi non "WebContent", questo è per i file web come JSP. Di seguito è riportato un esempio della struttura delle cartelle di un progetto Web dinamico Eclipse predefinito come mostrato nella vista Navigatore :
EclipseProjectName
|-- src
| `-- com
| `-- example
| `-- YourServlet.java
|-- WebContent
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Nel caso di un progetto Maven, la classe deve essere inserita nella struttura del pacchetto all'interno main/java
e quindi nonmain/resources
, ad esempio , questo è per i file non di classe . Di seguito è riportato un esempio della struttura delle cartelle di un progetto webapp Maven predefinito come mostrato nella vista Navigator di Eclipse :
MavenProjectName
|-- src
| `-- main
| |-- java
| | `-- com
| | `-- example
| | `-- YourServlet.java
| |-- resources
| `-- webapp
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Notare che la /jsps
sottocartella non è strettamente necessaria. Puoi anche farne a meno e mettere il file JSP direttamente in webcontent / webapp root, ma sto solo riprendendo questo dalla tua domanda.
Imposta l'URL del servlet in url-pattern
L'URL del servlet viene specificato come "pattern URL" della mappatura del servlet. Non è assolutamente per definizione il nome della classe / nome del file della classe servlet. Il pattern URL deve essere specificato come valore @WebServlet
dell'annotazione.
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.
// ...
}
Nel caso in cui desideri supportare parametri di percorso come /servlet/foo/bar
, utilizza invece un pattern URL /servlet/*
. Vedi anche Servlet e parametri di percorso come / xyz / {value} / test, come mappare in web.xml?
@WebServlet
funziona solo su Servlet 3.0 o più recente
Per poterlo utilizzare @WebServlet
, devi solo assicurarti che il tuo web.xml
file, se presente (è opzionale dal Servlet 3.0), sia dichiarato conforme alla versione Servlet 3.0+ e quindi non conforme ad es. Versione 2.5 o inferiore . Di seguito è riportato uno compatibile con Servlet 4.0 (che corrisponde a Tomcat 9+, WildFly 11+, Payara 5+, ecc.).
<?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>
Oppure, nel caso in cui non sei ancora su Servlet 3.0+ (ad esempio Tomcat 6 o precedente), rimuovi l' @WebServlet
annotazione.
package com.example;
public class YourServlet extends HttpServlet {
// ...
}
E registra invece il servlet in web.xml
questo modo:
<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>
Nota quindi che non dovresti usare entrambi i modi. Utilizza una configurazione basata su annotazioni o una configurazione basata su XML. Quando si dispone di entrambi, la configurazione basata su XML sovrascriverà la configurazione basata sull'annotazione.
Verifica della build / distribuzione
Nel caso in cui si utilizzi uno strumento di compilazione come Eclipse e / o Maven, è necessario assicurarsi assolutamente che il file di classe servlet compilato risieda nella sua struttura del pacchetto nella /WEB-INF/classes
cartella del file WAR prodotto. In caso di package com.example; public class YourServlet
, deve essere situato in /WEB-INF/classes/com/example/YourServlet.class
. Altrimenti dovrai affrontare @WebServlet
anche un errore 404 o <servlet>
un errore HTTP 500 come di seguito:
Stato HTTP 500
Errore durante la creazione dell'istanza della classe servlet com.example.YourServlet
E trova nel registro del server a java.lang.ClassNotFoundException: com.example.YourServlet
, seguito da a java.lang.NoClassDefFoundError: com.example.YourServlet
, a sua volta seguito da javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
.
Un modo semplice per verificare se il servlet è correttamente compilato e inserito nel classpath è lasciare che lo strumento di compilazione produca un file WAR (ad es. Clic destro progetto, Esporta> file WAR in Eclipse) e quindi ispezionarne il contenuto con uno strumento ZIP. Se la classe servlet non è presente /WEB-INF/classes
, o se l'esportazione causa un errore, allora il progetto è configurato male o alcuni valori predefiniti di IDE / configurazione del progetto sono stati erroneamente ripristinati (es. Progetto> Build Automatically è stato disabilitato in Eclipse).
È inoltre necessario assicurarsi che l'icona del progetto non abbia una croce rossa che indica un errore di compilazione. È possibile trovare l'errore esatto nella vista Problemi ( Finestra> Mostra vista> Altro ... ). Di solito il messaggio di errore va bene Googlable. Nel caso in cui non si abbia la minima idea, è meglio riavviare da zero e non toccare le impostazioni predefinite di IDE / progetto. Se utilizzi Eclipse, puoi trovare le istruzioni in Come importare l'API javax.servlet nel mio progetto Eclipse?
Testare il servlet individualmente
A condizione che il server sia in esecuzione localhost:8080
e che WAR sia stato distribuito con successo su un percorso di contesto di /contextname
(che ha come impostazione predefinita il nome del progetto IDE, distinzione tra maiuscole e minuscole!), E il servlet non ha fallito la sua inizializzazione (leggi i log del server per qualsiasi deploy / messaggi di successo / errore del servlet e il percorso del contesto effettivo e la mappatura del servlet), quindi /servlet
è disponibile un servlet con pattern URL di http://localhost:8080/contextname/servlet
.
Puoi semplicemente inserirlo direttamente nella barra degli indirizzi del browser per testarlo invidivamente. Se doGet()
è correttamente sovrascritto e implementato, vedrai il suo output nel browser. Oppure, se non ne hai doGet()
o se chiama in modo errato super.doGet()
, verrà mostrato un errore " HTTP 405: il metodo HTTP GET non è supportato da questo URL " (che è comunque migliore di un 404 poiché un 405 è la prova che il servlet stesso è effettivamente trovato).
L'override service()
è una cattiva pratica, a meno che tu non stia reinventando un framework MVC - il che è molto improbabile se stai appena iniziando con i servlet e non hai idea del problema descritto nella domanda corrente;) Vedi anche Applicazioni basate sul web di Design Patterns .
Indipendentemente da ciò, se il servlet restituisce già 404 quando viene testato invidivamente, è del tutto inutile provare invece con un modulo HTML. Logicamente, è quindi anche del tutto inutile includere qualsiasi modulo HTML nelle domande sugli errori 404 da un servlet.
Riferimento all'URL del servlet da HTML
Dopo aver verificato che il servlet funzioni correttamente se richiamato singolarmente, puoi passare all'HTML. Per quanto riguarda il tuo problema concreto con il modulo HTML, il <form action>
valore deve essere un URL valido. Lo stesso vale per <a href>
. Devi capire come funzionano gli URL assoluti / relativi. Sai, un URL è un indirizzo web che puoi inserire / vedere nella barra degli indirizzi del browser web. Se stai specificando un URL relativo come azione del modulo, cioè senza lo http://
schema, allora diventa relativo all'URL corrente come vedi nella barra degli indirizzi del tuo browser web. Non è quindi assolutamente relativo alla posizione del file JSP / HTML nella struttura delle cartelle WAR del server come sembrano pensare molti starter.
Quindi, supponendo che la pagina JSP con il modulo HTML sia aperta da http://localhost:8080/contextname/jsps/page.jsp
, e devi sottometterti a un servlet situato in http://localhost:8080/contextname/servlet
, ecco diversi casi (nota che puoi tranquillamente sostituire <form action>
con <a href>
qui):
L'azione del modulo viene inviata a un URL con una barra iniziale.
<form action="/servlet">
La barra iniziale /
rende l'URL relativo al dominio, quindi il modulo verrà inviato a
http://localhost:8080/servlet
Ma questo probabilmente si tradurrà in un 404 poiché è nel contesto sbagliato.
L'azione del modulo viene inviata a un URL senza una barra iniziale.
<form action="servlet">
Ciò rende l'URL relativo alla cartella corrente dell'URL corrente, quindi il modulo verrà inviato a
http://localhost:8080/contextname/jsps/servlet
Ma questo probabilmente si tradurrà in un 404 poiché si trova nella cartella sbagliata.
L'azione del modulo viene inviata a un URL che sale di una cartella.
<form action="../servlet">
Questo farà salire di una cartella (esattamente come nei percorsi del file system del disco locale!), Quindi il modulo verrà inviato a
http://localhost:8080/contextname/servlet
Questo deve funzionare!
L'approccio canonico, tuttavia, consiste nel rendere l'URL relativo al dominio in modo da non dover correggere nuovamente gli URL quando si sposta i file JSP in un'altra cartella.
<form action="${pageContext.request.contextPath}/servlet">
Questo genererà
<form action="/contextname/servlet">
Che quindi invierà sempre all'URL corretto.
Usa virgolette semplici in HTML
Devi essere assolutamente sicuro di usare virgolette semplici negli attributi HTML come action="..."
o action='...'
e quindi non virgolette come action=”...”
oaction=’...’
. Le virgolette curve non sono supportate in HTML e diventeranno semplicemente parte del valore.
Guarda anche:
Altri casi di errore di stato HTTP 404: