JavaRush /Java Blog /Random-IT /Creare una semplice applicazione web utilizzando servlet ...
Стас Пасинков
Livello 26
Киев

Creare una semplice applicazione web utilizzando servlet e jsp (parte 1)

Pubblicato nel gruppo Random-IT
Livello di conoscenza richiesto per comprendere l'articolo: hai già più o meno capito Java Core e vorresti approfondire le tecnologie JavaEE e la programmazione web. Ha più senso se stai attualmente studiando la ricerca sulle raccolte Java, che copre argomenti vicini all'articolo. Creare una semplice applicazione web utilizzando servlet e jsp (parte 1) - 1Questo materiale è una continuazione logica del mio articolo Creazione di un semplice progetto web in IntelliJ Idea Enterprise . In esso ho dimostrato come creare un modello di progetto web funzionante. Questa volta ti mostrerò come creare un'applicazione web semplice ma carina utilizzando le tecnologie Java Servlet API e JavaServer Pages API. La nostra applicazione avrà una home page con due collegamenti:
  • alla pagina di aggiunta dell'utente;
  • alla pagina di visualizzazione dell'elenco utenti.
Utilizzerò ancora IntelliJ Idea Enterprise Edition, Apache Maven (includi solo alcune dipendenze) e Apache Tomcat. Alla fine “decoreremo” la nostra applicazione utilizzando il framework W3.CSS . Partiremo dal presupposto che al momento tu abbia già un progetto vuoto, che svilupperemo qui. In caso contrario, leggi il primo articolo e fallo. Ci vorranno solo pochi minuti :)

Un po 'sulla struttura della futura applicazione

La nostra pagina principale ( / ) sarà la più ordinaria pagina html statica con un'intestazione e due collegamenti/pulsanti:
  • aggiungi un nuovo utente (verrà inviato a /add );
  • visualizzare l'elenco degli utenti (invia a /list ).
Tomcat catturerà le richieste a questi indirizzi e le invierà a una delle due servlet che realizzeremo (descriveremo la mappatura nel file web.xml ). E i servlet, a loro volta, elaboreranno le richieste, prepareranno i dati (o li salveranno se viene aggiunto un utente) e trasferiranno il controllo ai file jsp corrispondenti, che già “renderizzeranno” il risultato. Memorizzeremo i dati nell'elenco più comune (Elenco).

Creiamo una home page statica

Se hai index.jsp nella tua cartella web , cancellalo. Invece in questa cartella creeremo un semplice file html chiamato index.html :
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My super project!</title>
</head>
<body>
    <!-- header -->
    <div>
        <h1>Super app!<//h1>
    </div>

    <div>       <!-- content -->
        <div>    <!-- buttons holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
Non c'è niente di complicato qui. Nel titolo indichiamo il titolo della nostra pagina. Nel corpo della pagina abbiamo due div principali: header (intestazione) e content (contenuto). Nel contenuto abbiamo un supporto per i nostri pulsanti, anzi due pulsanti che, se cliccati, vengono inviati agli indirizzi appropriati. Puoi eseguire il progetto e vedere come appare ora. Se clicchi sui pulsanti, si aprono pagine con errore 404 perché non le abbiamo ancora. Ma questo suggerisce che i pulsanti funzionano. Vorrei notare che questa non è l'opzione più universale, perché se improvvisamente hai JavaScript disabilitato, questi pulsanti non saranno più utili nel browser. Ma supponiamo che nessuno abbia disabilitato JavaScript :). È chiaro che si potrebbero usare link semplici, ma io preferisco i pulsanti. Fai quello che ti piace di più. E non guardare il fatto che nei miei esempi ci saranno molti div . Poi li riempiremo di stili e tutto sembrerà più bello :).

Crea file jsp per eseguire il rendering del risultato

Nella stessa directory web creeremo una cartella in cui inseriremo i nostri file jsp . L'ho chiamato visualizzazioni e, ancora una volta, puoi improvvisare. In questa cartella creeremo due file jsp:
  • add.jsp — pagina per aggiungere utenti;
  • list.jsp - pagina per visualizzare un elenco di utenti.
Diamo loro i titoli di pagina appropriati. Qualcosa come "Aggiungi nuovo utente" e "Elenco utenti", e per ora lo lasceremo così.

Creiamo due servlet

Le servlet accetteranno ed elaboreranno le richieste che Tomcat passerà loro. Nella cartella src/main/java creeremo un pacchetto dell'app , che conterrà i nostri sorgenti. Lì avremo pacchetti più diversi. Pertanto, affinché questi pacchetti non vengano creati uno dentro l'altro, creiamo una classe nel pacchetto dell'app (quindi eliminiamola). Ora creiamo tre diversi pacchetti nel pacchetto dell'app :
  • entità : è qui che si troveranno le nostre entità (la classe stessa, che descriverà gli oggetti utente);
  • modello : il nostro modello sarà qui (ne parleremo più avanti);
  • servlet - beh, ecco i nostri servlet.
Successivamente, puoi rimuovere in sicurezza quella classe dal pacchetto dell'app (se l'hai creata tu, ovviamente). Nel pacchetto servlet creeremo due classi:
  • AddServlet : elaborerà le richieste ricevute in /add ;
  • ListServlet : elaborerà le richieste ricevute in /list .

Connessione delle dipendenze in Maven

Tomcat versione 9.* implementa le specifiche Servlet versione 4.0 e JavaServer Pages versione 2.3. Questo è scritto nella documentazione ufficiale di Tomcat 9 nel primo paragrafo della seconda riga. Ciò significa che se tu, come me, utilizzi questa versione di Tomcat, il codice che scriviamo e inviamo per l'esecuzione utilizzerà esattamente le versioni specificate. Ma vorremmo avere queste specifiche nel nostro progetto, in modo che il nostro codice che le utilizza venga almeno compilato con successo. E per questo dobbiamo caricarli nel nostro progetto. È qui che Maven viene in soccorso.

La regola generale è questa: se hai bisogno di connettere qualcosa al tuo progetto usando Maven:

  • vai al sito web del repository Maven;
  • cerca lì la libreria che ti serve e la versione che ti serve;
  • ottieni il codice di dipendenza che deve essere inserito nel tuo pom.xml;
  • inserire! :)
Quindi cominciamo. Per prima cosa prepariamo un file pom . Da qualche parte dopo /version ma prima di /project , inserisci quanto segue:
<dependencies>

</dependencies>
Pertanto, abbiamo indicato che all'interno di questi tag elencheremo le dipendenze di cui abbiamo bisogno. Ora vai su mvnrepository.com , ci sarà un campo di ricerca in alto. Innanzitutto, inserisci servlet nella ricerca. Il primo risultato, in cui gli usi sono più di settemila, ci va bene. Ricordiamo che ci occorre la versione 4.0 (per Tomcat 9; per altre versioni potrebbero essere adatte implementazioni più vecchie). Questa è una versione abbastanza recente, quindi non ci sono molti usi, ma è quella di cui abbiamo bisogno. Si aprirà una pagina in cui potrai ottenere il codice per questa dipendenza per vari gestori di pacchetti e potrai anche semplicemente scaricarlo. Ma poiché vogliamo collegarlo utilizzando Maven, selezioniamo il codice nella scheda Maven. Copiamo e incolliamo nel nostro file pom all'interno della sezione dipendenze. Se appare una notifica nell'angolo in basso a destra di IDEA che ci chiede se vogliamo abilitare l'importazione automatica, siamo d'accordo. Se hai rifiutato accidentalmente, vai su "Impostazioni" e abilita l'importazione automatica manualmente: Impostazioni (Ctrl + Alt + S) -> Compila, Esecuzione, Distribuzione -> Maven -> Importazione Ciò manterrà il file pom e i file di configurazione IDEA per questo progetto in sincronia. Ora, utilizzando lo stesso principio, troveremo e collegheremo JavaServer Pages versione 2.3 (inserisci jsp nella ricerca). E visto che abbiamo già utilizzato Maven, diciamo subito che i nostri sorgenti rispettano la sintassi di Java 8 e che devono essere compilati nel bytecode della stessa versione. Dopo tutte queste manipolazioni, il nostro pom.xml sarà simile a questo:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ru.javarush.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compile.source>
        <maven.compiler.target>1.8</maven.compile.target>
    </properties>

    <dependencies>
        <!-- Servlet API 4.0 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JavaServer Pages API 2.3 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

Rendere i nostri servlet veri e propri servlet

A questo punto, la coppia di servlet che abbiamo creato sono in realtà solo classi normali. Non hanno alcuna funzionalità. Ma ora abbiamo collegato l'API Servlet al nostro progetto e, in tal caso, possiamo utilizzare le classi da lì. Per rendere le nostre servlet “vere” servlet, dobbiamo semplicemente ereditarle dalla classe HttpServlet .

Mappatura o partizionamento

Ora sarebbe carino dire in qualche modo a Tomcat in modo che le richieste da /add siano gestite dal nostro servlet AddServlet e quindi le richieste da /list siano gestite dal servlet ListServlet . Questo processo è chiamato mappatura . Questo viene fatto nel file web.xml secondo questo principio:
  • per prima cosa descriviamo la servlet (diamo un nome e indichiamo il percorso della classe stessa);
  • quindi leghiamo questa servlet a un indirizzo specifico (indichiamo il nome della servlet che le abbiamo appena assegnato e indichiamo l'indirizzo da cui devono essere inviate le richieste a questa servlet).
Descriviamo la servlet:
<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
Ora lo leghiamo all'indirizzo:
<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
Come puoi vedere, il nome del servlet è lo stesso in entrambi i casi. Grazie a questo, Tomcat sa che se una richiesta arriva all'indirizzo /add , deve essere passata al servlet app.servlets.AddServlet . Facciamo lo stesso con il secondo servlet. Di conseguenza, il nostro web.xml ha approssimativamente il seguente contenuto:
<?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_3_1.xsd"
         version="3.1">

    <!-- add servlet -->
    <servlet>
        <servlet-name>add</servlet-name>
        <servlet-class>app.servlets.AddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>add</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>

    <!-- list servlet -->
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>app.servlets.ListServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/list</url-pattern>
    </servlet-mapping>
</web-app>
A proposito, non abbiamo creato il markup per la pagina principale qui (in / ). Il fatto è che in questo caso non ne abbiamo bisogno. La nostra home page è un semplice file html che visualizza semplicemente due pulsanti. Non c'è contenuto dinamico, quindi non ha senso per noi creare una servlet separata, alla quale verranno inviate le richieste dall'indirizzo / e che non farà altro che trasferire l'esecuzione su qualche jsp (che dovrebbe anche essere creato), che disegnerebbe Se solo avessimo due pulsanti. Non ne abbiamo bisogno; siamo soddisfatti di una risorsa statica. Quando Tomcat riceve una richiesta, controllerà che non ci sia un singolo servlet che possa elaborare la richiesta a tale indirizzo, e poi vedrà che a questo indirizzo c'è effettivamente un file html già pronto , che invierà con successo . Possiamo eseguire nuovamente la nostra applicazione (riavviare il server o ridistribuirla, come desideri) e assicurarci che la pagina principale sia renderizzata, che nulla sia rotto, quando facciamo clic sui pulsanti, si verificano transizioni, ma per ora c'è anche un errore scritto. A proposito, se prima avevamo un errore 404, ora abbiamo un 405. Ciò significa che la mappatura ha funzionato, le servlet sono state trovate, ma semplicemente non avevano metodi adatti per elaborare la richiesta. Se in questa fase ricevi ancora un errore 404, anche se tutto è stato fatto correttamente, forse dovresti correggere la configurazione di distribuzione nell'idea. Per fare ciò, bisogna andare su Modifica configurazioni (in alto vicino al pulsante di avvio), andare nella scheda Deployment sul lato destro della finestra e assicurarsi che in Contesto applicazione sia semplicemente indicato /

Una breve digressione lirica: cosa sta succedendo “sotto il cofano”?

Probabilmente ti sei già chiesto come funziona la nostra applicazione in Tomcat? Cosa sta succedendo là? E dov'è il metodo main() ? Non appena si digita localhost:8080 nel browser e si accede a questo indirizzo, il browser invia una richiesta a questo indirizzo tramite il protocollo http . Spero che tu sia già consapevole che le richieste possono essere di diversi “tipi”, le più popolari sono GET e POST . Ogni richiesta deve avere una risposta. La richiesta GET prevede che in risposta gli venga fornito un codice html già pronto , che verrà restituito al browser, e il browser sostituirà magnificamente questo codice con tutti i tipi di lettere, pulsanti e moduli. La richiesta POST è un po' più interessante, poiché porta con sé anche alcune informazioni. Ad esempio, nel modulo di registrazione o di autorizzazione dell'utente, hai inserito i tuoi dati e hai cliccato su “invia”. In questo momento, è stata inviata una richiesta POST al server con le tue informazioni personali all'interno. Il server ha accettato queste informazioni, le ha elaborate e ha restituito un qualche tipo di risposta (ad esempio, una pagina html con il tuo profilo). La differenza fondamentale tra loro è che le richieste GET sono destinate solo a ricevere dati dal server, mentre le richieste POST portano con sé alcune informazioni e i dati sul server possono cambiare (ad esempio, quando carichi la tua foto sul server, volerà nella richiesta POST e il server la aggiungerà al database, ovvero si verificherà qualche modifica. Ora torniamo a Tomcat. Quando riceve qualche richiesta dal client, guarda l'indirizzo. Cerca i suoi dati in vedere se esiste una servlet adatta, che elabori le richieste a tale indirizzo (o una risorsa già pronta che possa essere restituita subito).Se non trova nulla da restituire, risponde non con una pagina html, ma con una risposta 404. Se trova una servlet adatta, che "si trova" su questo indirizzo, esamina il tipo di richiesta che ha ricevuto (GET, POST o qualche altro), quindi chiede alla servlet se ha un metodo che potrebbe gestire questo tipo di richiesta.Se il servlet dice che non può elaborare questo tipo, Tomcat risponde al client con il codice 405. Questo è quello che ci è appena successo. Ma se viene trovato un servlet adatto e ha un metodo adatto, Tomcat crea un oggetto di questo servlet, lo esegue in un nuovo thread ( thread ), che consente al servlet di funzionare in un thread separato e Tomcat continua a lavorare ulteriormente nel proprio, ricevendo e inviando richieste. Inoltre, Tomcat crea altri due oggetti: uno di tipo HttpServletRequest (lo chiamerò brevemente richiesta in futuro), e il secondo di tipo HttpServletResponse(La chiamerò la risposta). Nel primo oggetto inserisce tutti i dati ricevuti in una richiesta dal client, in modo che tutti i dati possano essere estratti da questo oggetto. Bene, dopo tutto questo, passa questi due oggetti al metodo appropriato della servlet che è in esecuzione in un thread separato. Non appena il servlet termina il suo lavoro e ha una risposta pronta da inviare al client, invia un flag a Tomcat, dicendo: "Ho finito, tutto è pronto". Tomcat accetta la risposta e la invia al client. Ciò consente a Tomcat di accettare richieste e inviare risposte senza interruzioni, mentre tutto il lavoro viene svolto da servlet in esecuzione in thread separati. Di conseguenza, quando scriviamo il codice servlet, definiamo il lavoro che verrà eseguito. E sì, puoi pensare al metodo main() come se fosse nello stesso Tomcat (sì, è scritto in Java) e quando "avviiamo" Tomcat, il file main().

Catturiamo i metodi GET con servlet e inviamo risposte semplici

Al momento le nostre servlet non hanno metodi adatti (GET), quindi Tomcat ci restituisce un errore 405. Realizziamoli! La classe HttpServlet , da cui ereditiamo le nostre servlet, definisce diversi metodi. Per impostare del codice per i metodi, li sovrascriviamo semplicemente. In questo caso, dobbiamo sovrascrivere il metodo doGet() in entrambi i servlet.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
Come puoi vedere, questo metodo accetta due oggetti: req (richiesta) e resp (risposta). Questi sono gli oggetti che Tomcat creerà e popolerà per noi quando chiamerà il metodo appropriato in questo servlet. Per prima cosa, facciamo le risposte più semplici. Per fare ciò, prendi l' oggetto resp e ottieni da esso un oggetto PrintWriter , che può essere utilizzato per comporre risposte. Bene, usandolo stamperemo una semplice stringa.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("Method GET from AddServlet");
}
Faremo qualcosa di simile nel servlet ListServlet , dopodiché avvieremo nuovamente il nostro server. Come puoi vedere, funziona tutto! Cliccando sui pulsanti si aprono le pagine con il testo che abbiamo “registrato” con PrintWriter . È solo che il nostro jsp che abbiamo preparato per generare pagine con risposte non viene utilizzato in alcun modo. Questo perché l'esecuzione semplicemente non li raggiunge. Il serverlet stesso ora genera una risposta e termina il proprio lavoro, segnalando a Tomcat che ha una risposta pronta per il client. Tomcat prende semplicemente questa risposta e la rimanda al client. Trasferiamo il controllo dalle servlet alle jsp, cambiamo il codice dei nostri metodi in questo modo:
  • otteniamo dall'oggetto request un oggetto request manager, dove passiamo l' indirizzo jsp della pagina a cui vogliamo trasferire il controllo;
  • utilizzando l'oggetto ricevuto, trasferiamo il controllo alla pagina jsp specificata e non dimentichiamo di allegare lì gli oggetti di richiesta e risposta che abbiamo ricevuto da Tomcat.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
Nel corpo delle pagine jsp (all'interno del tag body) possiamo scrivere qualcosa in modo da poter vedere chiaramente quale pagina viene visualizzata. Successivamente, riavviamo il server e controlliamo. Vengono premuti i pulsanti sulla pagina principale, le pagine vengono aperte, il che significa che le richieste vengono inviate ai servlet, dopodiché il controllo viene trasferito alle pagine jsp, che sono già renderizzate. È tutto. Nella parte successiva dell'articolo tratteremo le funzionalità della nostra applicazione.

Cos'altro leggere:

Creazione di un semplice progetto web in IntelliJ Idea Enterprise. Passo dopo passo, con le immagini


La mia chiacchierata
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION