Il servlet restituisce "Stato HTTP 404 La risorsa richiesta (/ servlet) non è disponibile"


95

Ho un modulo HTML in un file JSP nella mia WebContent/jspscartella. Ho una classe servlet servlet.javanel mio pacchetto predefinito nella srccartella. Nel mio web.xmlè mappato come /servlet.

Ho provato diversi URL actionnell'attributo del modulo HTML:

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

Ma nessuno di questi funziona. Continuano tutti a restituire un errore HTTP 404 come di seguito in Tomcat 6/7/8:

Stato HTTP 404 - / servlet

Descrizione : la risorsa richiesta (/ servlet) non è disponibile.

O come sotto in Tomcat 8.5 / 9:

Stato HTTP 404 - Non trovato

Messaggio : / servlet

Descrizione : il server di origine non ha trovato una rappresentazione corrente per la risorsa di destinazione o non è disposto a rivelarne l'esistenza

Perché non funziona?

Risposte:


127

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 /jspssottocartella 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 @WebServletdell'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.xmlfile, 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' @WebServletannotazione.

package com.example;

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

E registra invece il servlet in web.xmlquesto 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/classescartella 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 @WebServletanche 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:8080e 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:


1
versione web-app = "3.1" usando glassfish, ho potuto testare il mio servlet individualmente bene quando avevo una mappatura in web.xml E l'annotazione. Ho rimosso la mappatura e ho lasciato l'annotazione poiché ho l'ultima versione ma poi avrei ricevuto un errore 404?
SallyRothroat

1
Ciò può accadere se si includono librerie servlet 2.5 o precedenti nella stessa webapp invece di fare affidamento sul runtime di destinazione per fornire le librerie servlet da solo.
BalusC

@xdola: è davvero fragile perché dipende dall'URI della richiesta. Basta leggere la risposta per la spiegazione del problema e qual è l'approccio corretto.
BalusC

4

Scenario n. 1: hai accidentalmente ridistribuito dalla riga di comando mentre Tomcat era già in esecuzione .

Risposta breve: arresta Tomcat, elimina la cartella di destinazione , il pacchetto mvn, quindi ridistribuisci


Scenario n. 2: request.getRequestDispatcher (" MIS_SPELLED_FILE_NAME .jsp")

Risposta breve: controlla l' ortografia del nome del file , assicurati che il caso sia corretto.


Scenario n. 3: Eccezioni di classe non trovata (risposta inserita qui perché: Domanda n. 17982240) ( java.lang.ClassNotFoundException per servlet in tomcat con eclipse ) (è stato contrassegnato come duplicato e mi ha indirizzato qui)

Risposta breve # 3.1: web.xml ha un percorso del pacchetto errato nel tag di classe servlet.

Risposta breve # 3.2: il file java ha un'istruzione di importazione errata.


Di seguito sono riportati ulteriori dettagli per lo scenario n. 1:


1: Ferma Tomcat

  • Opzione 1: tramite CTRL + C nel terminale.
  • Opzione 2: (terminale chiuso mentre Tomcat è ancora in esecuzione)
  • ------------ 2.1: premere: Windows + R -> digitare: " services.msc "
  • ------------ 2.2: Trova "Apache Tomcat #. # Tomcat #" nella colonna Nome dell'elenco.
  • ------------ 2.3: clic destro -> " stop "

2: Elimina la cartella "target". (mvn clean non ti aiuterà qui)

3: pacchetto mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE

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

Storia completa:


Ho aperto accidentalmente una nuova finestra git-bash e ho provato a distribuire un file .war per il mio progetto heroku tramite:

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

Dopo un errore di distribuzione, mi sono reso conto che avevo due finestre git-bash aperte e non avevo usato CTLR + C per interrompere la distribuzione precedente .

Sono stato accolto con:

Stato HTTP 404 - Rapporto sullo stato del tipo non trovato

Messaggio /if-student-test.jsp

Descrizione Il server di origine non ha trovato una rappresentazione corrente per la risorsa di destinazione o non è disposto a rivelare che esiste.

Apache Tomcat / 8.5.31

Di seguito sono riportati ulteriori dettagli per lo scenario n. 3:


SCENARIO 3.1: Il percorso del pacchetto della classe servlet è sbagliato nel file web.xml.

Dovrebbe CORRISPONDERE all'istruzione del pacchetto all'inizio della classe servlet java.

File: my_stuff / MyClass.java :

   package my_stuff;

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

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

SCENARIO 3.2:

Hai messo l' istruzione " pacchetto " sbagliata all'inizio del tuo file myClass.java.

Per esempio:

Il file si trova nella cartella : " / my_stuff "

Scrivi erroneamente:

package com.my_stuff

Questo è complicato perché:

1: La build di maven (pacchetto mvn) non riporterà alcun errore qui.

2: la riga della classe servlet in web.xml può avere il percorso del pacchetto CORRETTO. Per esempio:

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

Stack utilizzato: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10 :


Il tuo AppName.war e quindi il nome della cartella esplosa non corrispondono al tuo nome previsto, ad esempio quando il tuo file war ha una versione come AppName-1.0-SNAPSHOT.war e stai provando / AppName /.
jla

0

Soluzione per HTTP Status 404IDE NetBeans: fai clic con il pulsante destro del mouse sul progetto e vai alle proprietà del progetto, quindi fai clic su Esegui, quindi inserisci l'URL relativo del progetto come index.jsp.

  1. Progetto-> Proprietà
  2. Fare clic su Esegui
  3. URL relativo: /index.jsp (seleziona l'URL radice del progetto)

inserisci qui la descrizione dell'immagine


0

Il mio problema era che nel mio metodo mancava l'annotazione @RequestBody. Dopo aver aggiunto l'annotazione non ho più ricevuto l'eccezione 404.


0

Eseguire i due passaggi seguenti. Spero che risolva il problema "404 non trovato" nel server Tomcat durante lo sviluppo dell'applicazione servlet java.

Passo 1: Right click on the server(in the server explorer tab)->Properties->Switch Location from workspace metadata to tomcat server

Passo 2: Double Click on the server(in the server explorer tab)->Select Use tomcat installation option inside server location menu


0

Ho rimosso la vecchia libreria web in modo tale che fossero librerie di framework di primavera. E costruisci un nuovo percorso delle biblioteche. Allora funziona.


0

Un vecchio thread, ma poiché non l'ho trovato altrove, ecco un'altra possibilità:

Se stai utilizzando servlet-api 3.0+ , il tuo web.xml NON deve includere l' metadata-complete="true"attributo

inserisci qui la descrizione dell'immagine

Questo dice a Tomcat di mappare i servlet usando i dati forniti web.xmlinvece di usare l' @WebServletannotazione.


0

Prima di tutto, esegui il tuo IDE come amministratore. Successivamente, fai clic con il pulsante destro del mouse sulla cartella del progetto -> Project Facets e assicurati che la versione Java sia impostata correttamente. Sul mio PC. (Ad esempio 1.8) Ora dovrebbe funzionare.

Non avviare semplicemente il tuo server, ad esempio Wildfly, usando cmd. Deve essere avviato all'interno dell'IDE e ora visita il tuo URL localhost. Esempio: http: // localhost: 8080 / HelloWorldServlet / HelloWorld


0

La soluzione che ha funzionato per me è (se stai usando Maven): fai clic con il pulsante destro del mouse sul tuo progetto, Maven -> Aggiorna progetto. Questo potrebbe darti qualche altro errore con JDK e altre librerie (nel mio caso, connettore MySQL), ma una volta risolti, il tuo problema originale dovrebbe essere risolto!


0

Se desideri aprire un servlet con javascript senza utilizzare "form" e il pulsante "invia", ecco il codice seguente:

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

Chiave:

1) button-id: il tag 'id' che dai al tuo pulsante nel tuo file html / jsp.

2) full-servlet-path: il percorso che viene mostrato nel browser quando esegui il servlet da solo


0

La mappatura in web.xml è ciò che ho fatto: -

  1. Se c'è un altro pacchetto creato per il nuovo programma, dobbiamo menzionare: -

packagename.filename tra l'apertura e la chiusura del tag di classe servlet nel file xml.

  1. Se stai mappando i tuoi file in xml e non funzionano o mostrano errori, commenta la riga di annotazione del codice nei rispettivi file.

Entrambi i metodi non funzionano l'uno con l'altro, quindi o utilizzo il metodo di annotazione dei file menzionati quando creiamo servlet o il modo di mappare, quindi cancello o commento la riga di annotazione. Per esempio:

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

Commentando la riga di annotazione del codice nel rispettivo file, se la mappatura in xml è stata eseguita.

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

-1

Verifica che la root di contesto non possa essere vuota .

Se stai usando eclipse:
fai clic con il pulsante destro del mouse , seleziona proprietà , quindi impostazioni del progetto web . Verificare che la root di contesto non possa essere vuota

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.