CodeGym /Java blog /Tilfældig /Oprettelse af en simpel webapplikation ved hjælp af servl...
John Squirrels
Niveau
San Francisco

Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2)

Udgivet i gruppen
Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 1) Kendskab til at forstå artiklen: Du har allerede mere eller mindre fundet ud af Java Core og vil gerne se på JavaEE-teknologier og webprogrammering. Det ville give mest mening for dig i øjeblikket at studere Java Collections-questen, som omhandler emner tæt på artiklen.
Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2) - 1

Oprettelse af enheder

I entities- pakken opretter vi en Userklasse, der har to private strengvariabler: navn og adgangskode . Opret konstruktører (standard og en, der tager begge værdier) og gettere/sættere, og tilsidesæt metoden toString()for en sikkerheds skyld sammen med equals()og hashCode()metoderne. Med andre ord vil vi gøre alt, hvad en respektabel Java-udvikler gør, når de opretter en klasse.

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;
    }
}
Nu kan vi begynde at oprette en liste over brugere. Vi tilføjer brugere til det og tager brugere fra det for at vise dem. Vi har dog et problem. Vi opretter ikke vores servlet-objekter. Tomcat gør dette for os. De metoder, vi tilsidesætter i dem, er allerede defineret for os, og vi kan ikke parametrere. Hvordan opretter vi så en delt liste, der vil være synlig i begge vores servlets? Hvis vi bare opretter et listeobjekt i hver servlet, så ville vi tilføje brugere til en liste, men vise brugere fra en anden i ListServlet. Så vi har brug for et objekt, der deles af begge servlets. Generelt har vi brug for et objekt, der deles af alle klasserne i vores program: ét objekt for hele programmet. Jeg håber du har hørt noget om designmønstre. For nogle mennesker kan dette være det første rigtige behov for Singleton- mønsteret i deres program. Du kunne gå galt og skrue noget sødt Singleton frem med dobbelttjek og synkronisering (jep, vores applikation er multithreaded, da Tomcat-servlets kører på separate tråde). Men jeg vil bruge den tidlige initialiseringsteknik, fordi den er helt tilstrækkelig til vores formål her.

Oprettelse af en model

Opret en klasse (og implementer Singleton- mønsteret) i modelpakken og kald det noget usædvanligt. For eksempel Model . Vi opretter en privat liste over brugere i vores klasse og implementerer to metoder: en til at tilføje en bruger og en anden til at returnere en liste over strenge (brugernavne). Da vores brugerobjekt består af et brugernavn og en adgangskode, og vi ikke ønsker at afsløre brugeradgangskoder, har vi kun en liste med navne.

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());
    }
}

Lidt om MVC

Da du allerede har hørt om singleton , har du sikkert hørt om en anden design pattern model-view-controller (MVC). Dens formål er at adskille forretningslogik fra udsigten. Det vil sige at adskille koden, der bestemmer, hvad der skal gøres, fra koden, der bestemmer, hvordan man viser ting. Visningen er ansvarlig for , hvordan data præsenteres. I vores tilfælde er visningerne vores JSP-sider . Det er netop derfor, jeg lægger dem i en mappe med navnet views . Modellen er de data, programmet rent faktisk arbejder med. I vores tilfælde er dette brugerne (liste over brugere). Og controllere er bindeleddet mellem dem. De tager data fra modellen og videregiver dem til visningerne (eller får nogle data fra Tomcat, bearbejde det og videregive det til modellen). Du definerer din forretningslogik (hvad programmet skal gøre) i dem, ikke i modellen eller visningen. Således håndterer hver del sin egen forretning:
  • modellen gemmer data;
  • visninger giver smukke repræsentationer af dataene;
  • registeransvarlige varetager databehandlingen.
Dette gør det muligt for programmet at være ganske enkelt og vedligeholde, snarere end en monstrøs bunke af al koden i én klasse. MVC er ikke kun velegnet til webprogrammering, men det bruges især ofte på dette område (næsten altid). I vores tilfælde vil servlets fungere som controllere. Dette er en meget overfladisk og kort beskrivelse af mønsteret, men MVC er ikke hovedemnet i denne artikel. Hvis nogen vil lære mere, er Google din ven! Opret en formular til tilføjelse af en bruger. Tilføj formularen til add.jsp . Det skal bestå af to tekstindtastningsfelter (et almindeligt, det andet - et kodeordsfelt) og en knap til at sende data til serveren.

<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>
Her har formularen en metodeattribut med værdiposten . Dette indikerer, at dataene fra denne formular vil gå til serveren som en POST-anmodning . Action - attributten er ikke specificeret, hvilket betyder, at anmodningen vil blive sendt til den samme adresse, som vi kom til denne side fra ( /add ). Ved modtagelse af en GET-anmodning returnerer vores servlet bundet til denne adresse således JSP'en med tilføjelsesbrugerformularen. Og hvis den modtager en POST-anmodning , ved vi, at formularen sendte sine data her (som vi uddrager fra anmodningsobjektet idoPost()metode, proces og overførsel til modellen for at gemme). Det er værd at bemærke, at inputfelter har en parameter kaldet navn (for brugernavne eller adgangskoder ). Dette er et meget vigtigt punkt. For at modtage disse data (brugernavnet og adgangskoden, der vil blive indtastet) fra anmodningen (inde i servlet'en), bruger vi disse navne- og adgangsfelter . Men mere om det senere. Min knap til at sende data blev igen lavet som en knap , ikke som et outputfelt, som det er sædvanligt. Jeg ved ikke, hvor udbredt denne tilgang er, men den virker for mig (Chrome-browser).

Servlet-håndtering af POST-anmodninger

Lad os vende tilbage til AddServlet . Jeg minder dig om, at for at tillade vores servlet at "fange" GET-anmodninger , har vi tilsidesat doGet()metoden i HttpServlet- klassen. For at lære vores servlet også at fange POST-anmodninger , skal vi også tilsidesætte doPost()metoden. Tomcat sender den lignende anmodnings- og svarobjekter, som vi vil arbejde med. For at starte skal du udtrække anmodningens navn og sende parametre sendt af formularen (hvis du har angivet forskellige navne i formularen, så brug disse navne). Derefter skal du oprette et brugerobjekt ved hjælp af de modtagne data. Så får vi modelobjektet og tilføjer den oprettede bruger til modellen.

@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);
}

Sender data til visningen

Lad os gå videre til ListServlet . Metoden doGet()er allerede implementeret. Det overfører simpelthen kontrol til visningen ( list.jsp ). Hvis du ikke har dette endnu, så opret det analogt med metoden i AddServlet . Nu ville det være rart at få listen over brugernavne fra modellen og videregive dem til visningen, som vil modtage dem og vise dem smukt. For at gøre dette vil vi igen bruge anmodningsobjektet, vi modtog fra Tomcat . Vi kan tilføje en attribut til dette objekt, hvilket giver det en form for navn. Faktisk kan vi tilføje det objekt, vi vil sende til visningen. På grund af det faktum, at når vi overfører kontrol fra servlet'en til visningen, sender vi visningen de samme anmodnings- og svarobjekter, som servlet'en modtog, kan vi tilføje vores liste over navne til anmodningsobjektet og derefter få vores liste over brugernavne fra anmodningen objekt i visningen. Vi er færdige med ListServlet- klassen, så jeg vil præsentere koden for hele klassen her:

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);
    }
}

Kører Java-kode i JSP-filer

Det er tid til at se på list.jsp . Det vil kun blive udført, når ListServlet overfører kontrol til det. Derudover har vi allerede forberedt listen over brugernavne fra modellen i servlet'en og sendt den her i anmodningsobjektet. Da vi har listen over navne, kan vi gentage den ved hjælp af en forløkke og vise hvert navn. Som jeg sagde før, kan JSP-filer udføre Java-kode (hvilket er det, der gør dem anderledes end statiske HTML-sider). For at udføre noget kode er alt, hvad vi skal gøre, at sætte følgende konstruktion på det rigtige sted:

<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Inden for denne konstruktion får vi adgang til flere variabler:
  • request — our request object, som vi sendte fra servlet, hvor det blot hed req ;
  • response — responsobjektet (kaldet resp i servlet);
  • out — et JspWriter- objekt (som arver en almindelig Writer ), som vi kan bruge til at "skrive" noget direkte ind i selve HTML-siden . Udsagnet out.println("Hello, World!") ligner meget System.out.println("Hello, World!") , men lad være med at forveksle dem!
  • out.println() "skriver" til en HTML-side , mens System.out.println skriver til systemets output-stream . Hvis du kalder System.out.println() i en JSP- sektion med Java-kode , vil du se resultaterne i Tomcat- konsollen, men ikke på siden.
Du kan søge efter andre tilgængelige objekter i en JSP her . Vi kan bruge request -objektet til at få listen over navne sendt fra servlet'en (vi har knyttet den tilsvarende attribut til dette objekt), og vi får brugt out- objektet til at vise disse navne. Lad os vise dem (foreløbig som en simpel HTML-liste):

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

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
Hvis vi kun skal vise listen, hvis der er brugere, og ellers vise en advarsel om, at der ikke er nogen brugere endnu, så kan vi omskrive dette afsnit lidt:

<%
    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>");
%>
Nu hvor vi ved, hvordan vi overfører data fra servlets til visninger, kan vi forbedre vores AddServlet , så den viser en meddelelse om succesfuld tilføjelse af en bruger. For at gøre dette kan vi i doPost()metoden, efter at have tilføjet en ny bruger til modellen, tilføje dette brugernavn til req- objektets attributter og sende kontrollen tilbage til en visning ( add.jsp ). Og nu tilføjer vi en sektion med Java-kode, hvor vi kontrollerer, om anmodningen har en sådan egenskab, og hvis den gør det - så viser vi en meddelelse om, at brugeren er blevet tilføjet. Efter disse ændringer vil AddServlets fulde kode se sådan ud:

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);
    }
}
Her opretter vi i slutningen af doPost()​​metoden en attribut med navnet på den bruger, der blev tilføjet til modellen, og kalder derefter metoden doGet(), som vi videregiver den aktuelle anmodning og svar til. Metoden doGet()overfører nu kontrol til visningen, som også modtager anmodningsobjektet med navnet på den tilføjede bruger tilknyttet som en attribut. Det, vi skal gøre, er at rette add.jsp, så den viser meddelelsen, hvis der ikke er en sådan attribut. Her er den endelige version af 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>
Sideteksten består af følgende:
  • en div med en header;
  • en div-beholder til indhold, som inkluderer en kontrol af, om der findes en attribut med et brugernavn;
  • en div med tilføjelsesbrugerformularen;
  • og nederst en sidefod med en knap for at vende tilbage til startsiden.
Dette kan virke som for mange divs, men vi bruger dem senere, når vi tilføjer typografier. Her er den endelige version af 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>
Således har vi en fuldt fungerende webapplikation, der kan gemme og tilføje brugere og også vise en liste over deres navne. Nu mangler vi bare at gøre det smukt... :) Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2) - 2

Tilføjelse af stilarter. Vi bruger W3.CSS-rammerne

I øjeblikket virker vores applikation, men det ser helt skandaløst ud. Så lad os tilføje en baggrund, farvelægge teksten og knapperne, tilføje stil til listerne, justere elementer, tilføje indrykning og så videre. At skrive stile manuelt kan tage meget tid og belaste vores nerver. Så jeg foreslår at bruge W3.CSS- rammerne. Det har allerede klar-til-brug klasser med stilarter. Vi mangler bare at arrangere de CSS-klasser, vi vil bruge, de rigtige steder. For at tilføje dem til vores sider, forbinder vi først stilfilen. Der er to måder at gøre dette på:
  1. gå gennem vores sider og indsæt følgende et direkte link til stilfilen i hovedafsnittet

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

    Denne mulighed er velegnet, hvis du har en permanent internetforbindelse. Når du åbner dine sider på den lokale server, vil stilene blive trukket fra internettet.

  2. Men hvis du vil have alle stilene lokalt og ikke er afhængige af en internetforbindelse, skal du downloade stilfilen og placere den et sted inde i webmappen ( f.eks. web/styles/w3.css ). Gå derefter gennem alle vores sider ( index.html, add.jsp, list.jsp ) og tilføj følgende link til stilfilen inde i hovedsektionen :

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

    Derefter skal du bare gå gennem tags og tilføje de stilarter, du kan lide. Jeg vil ikke dvæle ved dette i detaljer. I stedet vil jeg bare levere klar-til-brug versioner af tre af mine filer med raster-stil klasser.

index.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>
list.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>
Og det er det. :) Hvis du stadig har spørgsmål eller kommentarer, eller hvis noget ikke virker, så læg en kommentar. Og jeg vil vedhæfte et par skærmbilleder af, hvordan det hele blev.
Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2) - 3
Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2) - 4
Oprettelse af en simpel webapplikation ved hjælp af servlets og JSP'er (del 2) - 5
Og endelig , hvis du vil øve dig med dette projekt, kan du prøve følgende:
  • lav en servlet og JSP for at slette en bruger, og tilføj endnu et par for at redigere en eksisterende bruger. Resultatet bliver en ægte CRUD-webapplikation bygget ved hjælp af servlets. ;)
  • erstatte listen med en database, så de tilføjede brugere ikke forsvinder, efter at serveren er genstartet. :)
Held og lykke!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION