CodeGym /Java Blog /Random-IT /Creazione di una semplice applicazione Web utilizzando se...
John Squirrels
Livello 41
San Francisco

Creazione di una semplice applicazione Web utilizzando servlet e JSP (parte 2)

Pubblicato nel gruppo Random-IT
Creazione di una semplice applicazione Web utilizzando servlet e JSP (parte 1) Conoscenze necessarie per comprendere l'articolo: hai già più o meno capito Java Core e vorresti esaminare le tecnologie JavaEE e la programmazione web. Sarebbe più sensato che tu stia attualmente studiando la ricerca Java Collections, che tratta argomenti vicini all'articolo.
Creazione di una semplice applicazione Web utilizzando servlet e JSP (parte 2) - 1

Creare entità

Nel pacchetto Entity , creeremo una Userclasse che ha due variabili stringa private: name e password . Crea costruttori (predefinito e uno che accetta entrambi i valori) e getter/setter e sovrascrivi il toString()metodo per ogni evenienza, insieme ai metodi equals()e hashCode(). In altre parole, faremo tutto ciò che fa uno sviluppatore Java rispettabile durante la creazione di una classe.

public class User {
    private String name;
    private String password;

    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return password != null ? password.equals(user.password) : user.password == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (password != null ? password.hashCode() : 0);
        return result;
    }
}
Ora possiamo iniziare a creare un elenco di utenti. Aggiungeremo gli utenti ad esso e prenderemo gli utenti da esso per visualizzarli. Tuttavia, abbiamo un problema. Non creiamo i nostri oggetti servlet. Tomcat fa questo per noi. I metodi che sovrascriviamo in essi sono già definiti per noi e non possiamo parametrizzarli. Come creiamo quindi un elenco condiviso che sarà visibile in entrambi i nostri servlet? Se creiamo solo un oggetto elenco in ogni servlet, aggiungeremo gli utenti a un elenco, ma visualizzeremo gli utenti di un altro nel ListServlet. Quindi abbiamo bisogno di un oggetto condiviso da entrambi i servlet. In generale, abbiamo bisogno di un oggetto condiviso da tutte le classi del nostro programma: un oggetto per l'intero programma. Spero che tu abbia sentito qualcosa sui design pattern. Per alcune persone, questa potrebbe essere la prima vera necessità del modello Singleton nel loro programma. Potresti impazzire e sfornare un dolce Singleton con doppi controlli e sincronizzazione (sì, la nostra applicazione è multithread, poiché i servlet Tomcat vengono eseguiti su thread separati). Ma userò la tecnica di inizializzazione anticipata, perché è del tutto adeguata per i nostri scopi qui.

Creazione di un modello

Crea una classe (e implementa il pattern Singleton ) nel pacchetto del modello e chiamala in modo insolito. Ad esempio, Modello . Creeremo un elenco privato di utenti nella nostra classe e implementeremo due metodi: uno per aggiungere un utente e un altro per restituire un elenco di stringhe (nomi utente). Poiché il nostro oggetto utente è costituito da un nome utente e una password e non vogliamo rivelare le password degli utenti, avremo solo un elenco di nomi.

public class Model {
    private static Model instance = new Model();

    private List<User> model;

    public static Model getInstance() {
        return instance;
    }

    private Model() {
        model = new ArrayList<>();
    }

    public void add(User user) {
        model.add(user);
    }

    public List<String> list() {
        return model.stream()
                .map(User::getName)
                .collect(Collectors.toList());
    }
}

Un po' di MVC

Dato che hai già sentito parlare di singleton , probabilmente hai sentito parlare di un altro modello di visualizzazione del controller (MVC) del modello di progettazione. Il suo scopo è separare la logica aziendale dalla vista. Cioè, per separare il codice che determina cosa fare dal codice che determina come visualizzare le cose. La vista è responsabile della modalità di presentazione dei dati. Nel nostro caso, le visualizzazioni sono le nostre pagine JSP . Questo è esattamente il motivo per cui li ho inseriti in una cartella denominata views . Il modello sono i dati con cui il programma lavora effettivamente. Nel nostro caso, si tratta degli utenti (elenco degli utenti). E i controller sono il collegamento tra di loro. Prendono i dati dal modello e li passano alle viste (o ottengono alcuni dati da Tomcat, elaborarlo e passarlo al modello). Definisci la tua logica aziendale (cosa dovrebbe fare il programma) in essi, non nel modello o nella vista. Pertanto, ciascuna parte gestisce la propria attività:
  • il modello memorizza i dati;
  • le viste rendono belle rappresentazioni dei dati;
  • i titolari gestiscono il trattamento dei dati.
Ciò consente al programma di essere abbastanza semplice e gestibile, piuttosto che un mostruoso mucchio di tutto il codice in una classe. MVC non è adatto solo per la programmazione web, ma è utilizzato soprattutto in quest'area (quasi sempre). Nel nostro caso, i servlet fungeranno da controllori. Questa è una descrizione molto superficiale e breve del modello, ma MVC non è l'argomento principale di questo articolo. Se qualcuno vuole saperne di più, Google è tuo amico! Crea un modulo per aggiungere un utente. Aggiungi il modulo a add.jsp . Dovrebbe consistere in due campi di immissione del testo (uno ordinario, l'altro - un campo password) e un pulsante per inviare i dati al server.

<form method="post">
    <label>Name:
        <input type="text" name="name"><br />
    </label>

    <label>Password:
        <input type="password" name="pass"><br />
    </label>
    <button type="submit">Submit</button>
</form>
Qui il form ha un attributo method con il valore post . Ciò indica che i dati di questo modulo andranno al server come richiesta POST . L' attributo action non è specificato, il che significa che la richiesta verrà inviata allo stesso indirizzo da cui siamo arrivati ​​a questa pagina ( /add ). Pertanto, dopo aver ricevuto una richiesta GET , il nostro servlet associato a questo indirizzo restituisce il JSP con il modulo add-user. E se riceve una richiesta POST , allora sappiamo che il modulo ha inviato i suoi dati qui (che estraiamo dall'oggetto richiesta neldoPost()metodo, processo e passaggio al modello per il salvataggio). Vale la pena notare che i campi di input hanno un parametro chiamato name (per i nomi utente o pass per le password). Questo è un punto molto importante. Pertanto, per ricevere questi dati (il nome utente e la password che verranno inseriti) dalla richiesta (all'interno del servlet), utilizzeremo questi campi name e pass . Ma ne parleremo più avanti. Il mio pulsante per l'invio dei dati è stato nuovamente creato come un pulsante , non come un campo di output come è consuetudine. Non so quanto sia ampiamente adottato questo approccio, ma funziona per me (browser Chrome).

Gestione servlet delle richieste POST

Torniamo all'AddServlet . Ti ricordo che per consentire alla nostra servlet di "catturare" le richieste GET , abbiamo sovrascritto il doGet()metodo nella classe HttpServlet . Per insegnare al nostro servlet a catturare anche le richieste POST , dobbiamo anche eseguire l'override del doPost()metodo. Tomcat gli passa oggetti di richiesta e risposta simili con cui lavoreremo. Per iniziare, estrai il nome della richiesta e passa i parametri inviati dal modulo (se hai specificato nomi diversi nel modulo, usa quei nomi). Successivamente, crea un oggetto utente utilizzando i dati ricevuti. Quindi otteniamo l'oggetto modello e aggiungiamo l'utente creato al modello.

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("pass");
    User user = new User(name, password);
    Model model = Model.getInstance();
    model.add(user);
}

Passaggio di dati alla vista

Passiamo al ListServlet . Il doGet()metodo è già implementato. Trasferisce semplicemente il controllo alla vista ( list.jsp ). Se non lo hai ancora, crealo per analogia con il metodo in AddServlet . Ora sarebbe bello ottenere l'elenco dei nomi utente dal modello e passarli alla vista, che li riceverà e li visualizzerà magnificamente. Per fare ciò, utilizzeremo nuovamente l'oggetto request che abbiamo ricevuto da Tomcat . Possiamo aggiungere un attributo a questo oggetto, dandogli un qualche tipo di nome. Possiamo infatti aggiungere l'oggetto che vogliamo passare alla vista. A causa del fatto che quando trasferiamo il controllo dal servlet alla vista passiamo alla vista gli stessi oggetti richiesta e risposta ricevuti dal servlet, possiamo aggiungere il nostro elenco di nomi all'oggetto richiesta e quindi ottenere il nostro elenco di nomi utente dalla richiesta oggetto nella vista. Abbiamo finito con la classe ListServlet , quindi presenterò qui il codice dell'intera classe:

package app.servlets;

import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Model model = Model.getInstance();
        List<String> names = model.list();
        req.setAttribute("userNames", names);

        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp");
        requestDispatcher.forward(req, resp);
    }
}

Esecuzione di codice Java nei file JSP

È tempo di guardare list.jsp . Verrà eseguito solo quando ListServlet gli trasferirà il controllo. Inoltre, abbiamo già preparato l'elenco dei nomi utente dal modello nel servlet e lo abbiamo passato qui nell'oggetto richiesta. Poiché abbiamo l'elenco dei nomi, possiamo iterare su di esso utilizzando un forciclo e visualizzare ogni nome. Come ho detto prima, i file JSP possono eseguire codice Java (che è ciò che li rende diversi dalle pagine HTML statiche). Per eseguire del codice, tutto ciò che dobbiamo fare è inserire il seguente costrutto nel posto appropriato:

<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
All'interno di questo costrutto, abbiamo accesso a diverse variabili:
  • request — il nostro oggetto request, che abbiamo passato dal servlet, dove si chiamava semplicemente req ;
  • risposta — l'oggetto risposta (chiamato resp nel servlet);
  • out — un oggetto JspWriter (che eredita un normale Writer ), che possiamo usare per "scrivere" qualcosa direttamente nella pagina HTML stessa. L'istruzione out.println("Hello, World!") è molto simile a System.out.println("Hello, World!") , ma non confonderli!
  • out.println() "scrive" in una pagina HTML , mentre System.out.println scrive nel flusso di output del sistema . Se chiami System.out.println() all'interno di una sezione JSP con codice Java , vedrai i risultati nella console Tomcat , ma non nella pagina.
Puoi cercare altri oggetti disponibili all'interno di una JSP qui . Possiamo utilizzare l' oggetto request per ottenere l'elenco dei nomi passati dal servlet (abbiamo allegato l'attributo corrispondente a questo oggetto) e utilizzare l' oggetto out per visualizzare questi nomi. Visualizziamoli (per il momento, come un semplice elenco HTML):

<ul>
    <%
        List<String> names = (List<String>) request.getAttribute("userNames");

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
Se abbiamo bisogno di visualizzare l'elenco solo se ci sono utenti, e altrimenti visualizzare un avviso che non ci sono ancora utenti, allora possiamo riscrivere un po' questa sezione:

<%
    List<String> names = (List<String>) request.getAttribute("userNames");

    if (names != null && !names.isEmpty()) {
        out.println("<ui>");
        for (String s : names) {
            out.println("<li>" + s + "</li>");
        }
        out.println("</ui>");
    } else out.println("<p>There are no users yet!</p>");
%>
Ora che sappiamo come passare i dati dai servlet alle viste, possiamo migliorare il nostro AddServlet in modo che visualizzi una notifica sull'aggiunta riuscita di un utente. Per fare ciò, nel doPost()metodo, dopo aver aggiunto un nuovo utente al modello, possiamo aggiungere questo nome utente agli attributi dell'oggetto req e ripassare il controllo a una vista ( add.jsp ). E ora aggiungeremo una sezione con codice Java, in cui verificheremo se la richiesta ha un tale attributo e, in caso affermativo, visualizzeremo un messaggio che l'utente è stato aggiunto correttamente. Dopo queste modifiche, il codice completo di AddServlet sarà simile a questo:

package app.servlets;

import app.entities.User;
import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
        requestDispatcher.forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String password = req.getParameter("pass");
        User user = new User(name, password);
        Model model = Model.getInstance();
        model.add(user);

        req.setAttribute("userName", name);
        doGet(req, resp);
    }
}
Qui, alla fine del doPost()metodo, creiamo un attributo con il nome dell'utente che è stato aggiunto al modello, quindi chiamiamo il doGet()metodo, a cui passiamo la richiesta e la risposta correnti. Il doGet()metodo ora trasferisce il controllo alla vista, che riceve anche l'oggetto richiesta con il nome dell'utente aggiunto allegato come attributo. Ciò che resta da fare è correggere add.jsp in modo che visualizzi la notifica se non esiste tale attributo. Ecco la versione finale di add.jsp :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
                }
            %>
            <div>
                <div>
                    <h2>Add user</h2>
                </div>

                <form method="post">
                    <label>Name:
                        <input type="text" name="name"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass"><br />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Il corpo della pagina è costituito da quanto segue:
  • un div con un'intestazione;
  • un contenitore div per il contenuto, che include un controllo se esiste un attributo con un nome utente;
  • un div con il modulo add-user;
  • e in basso, un piè di pagina con un pulsante per tornare alla home page.
Potrebbero sembrare troppi div, ma li useremo in seguito quando aggiungeremo gli stili. Ecco la versione finale di list.jsp :

<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <div>
                <div>
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ui>");
                        for (String s : names) {
                            out.println("<li>" + s + "</li>");
                        }
                        out.println("</ui>");
                    } else out.println("<p>There are no users yet!</p>");
                %>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Pertanto, abbiamo un'applicazione Web completamente funzionante che può salvare e aggiungere utenti e visualizzare anche un elenco dei loro nomi. Ora dobbiamo solo renderlo carino... :) Creazione di una semplice applicazione web utilizzando servlet e JSP (parte 2) - 2

Aggiunta di stili. Useremo il framework W3.CSS

Al momento, la nostra applicazione funziona, ma sembra assolutamente oltraggiosa. Quindi, aggiungiamo uno sfondo, coloriamo il testo ei pulsanti, aggiungiamo uno stile agli elenchi, allineiamo gli elementi, aggiungiamo i rientri e così via. Gli stili di scrittura manualmente possono richiedere molto tempo e mettere a dura prova i nostri nervi. Quindi propongo di utilizzare il framework W3.CSS . Ha già classi pronte all'uso con stili. Abbiamo solo bisogno di organizzare le classi CSS che vogliamo usare nei posti giusti. Per aggiungerli alle nostre pagine, prima colleghiamo il file di stile. Ci sono due modi per farlo:
  1. scorri le nostre pagine e inserisci di seguito un link diretto al file di stile nella sezione head

    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

    Questa opzione è adatta se disponi di una connessione Internet permanente. Quando apri le tue pagine sul server locale, gli stili verranno estratti da Internet.

  2. Ma se vuoi avere tutti gli stili localmente e non dipendere da una connessione Internet, scarica il file di stile e posizionalo da qualche parte all'interno della cartella web (es. web/styles/w3.css ). Quindi passa attraverso tutte le nostre pagine ( index.html, add.jsp, list.jsp ) e aggiungi il seguente collegamento al file di stile all'interno della sezione head :

    <link rel="stylesheet" href="styles/w3.css">

    Dopodiché, passa attraverso i tag e aggiungi gli stili che ti piacciono. Non mi soffermerò su questo in dettaglio. Invece, fornirò solo versioni pronte per l'uso di tre dei miei file con classi in stile raster.

indice.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Super app!</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center">
            <div class="w3-bar w3-padding-large w3-padding-24">
                <button class="w3-btn w3-hover-light-blue w3-round-large" onclick="location.href='/list'">List users</button>
                <button class="w3-btn w3-hover-green w3-round-large" onclick="location.href='/add'">Add user</button>
            </div>
        </div>
    </body>
</html>
add.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-padding">
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<div class=\"w3-panel w3-green w3-display-container w3-card-4 w3-round\">\n" +
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-green w3-border w3-border-green w3-hover-border-grey\">×</span>\n" +
                            "   <h5>User '" + request.getAttribute("userName") + "' added!</h5>\n" +
                            "</div>");
                }
            %>
            <div class="w3-card-4">
                <div class="w3-container w3-center w3-green">
                    <h2>Add user</h2>
                </div>
                <form method="post" class="w3-selection w3-light-grey w3-padding">
                    <label>Name:
                        <input type="text" name="name" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <button type="submit" class="w3-btn w3-green w3-round-large w3-margin-bottom">Submit</button>
                </form>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
lista.jsp

<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users list</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center w3-margin-bottom w3-padding">
            <div class="w3-card-4">
                <div class="w3-container w3-light-blue">
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ul class=\"w3-ul\">");
                        for (String s : names) {
                            out.println("<li class=\"w3-hover-sand\">" + s + "</li>");
                        }
                        out.println("</ul>");

                    } else out.println("<div class=\"w3-panel w3-red w3-display-container w3-card-4 w3-round\">\n"
+
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-red w3-border w3-border-red w3-hover-border-grey\">×</span>\n" +
                            "   <h5>There are no users yet!</h5>\n" +
                            "</div>");
                %>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
E questo è tutto. :) Se hai ancora domande o commenti, o se qualcosa non funziona, lascia un commento. E allego un paio di schermate di come è andata a finire.
Creazione di una semplice applicazione web utilizzando servlet e JSP (parte 2) - 3
Creazione di una semplice applicazione Web utilizzando servlet e JSP (parte 2) - 4
Creazione di una semplice applicazione web utilizzando servlet e JSP (parte 2) - 5
E infine , se vuoi esercitarti con questo progetto, puoi provare quanto segue:
  • creare un servlet e JSP per eliminare un utente e aggiungere un'altra coppia per modificare un utente esistente. Il risultato sarà una vera e propria applicazione web CRUD costruita utilizzando servlet. ;)
  • sostituire l'elenco con un database, in modo che gli utenti aggiunti non scompaiano dopo il riavvio del server. :)
Buona fortuna!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION