CodeGym /Java-blogg /Tilfeldig /Opprette en enkel nettapplikasjon ved hjelp av servlets o...
John Squirrels
Nivå
San Francisco

Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2)

Publisert i gruppen
Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 1) Kunnskap som kreves for å forstå artikkelen: Du har allerede mer eller mindre funnet ut av Java Core og vil gjerne se på JavaEE-teknologier og webprogrammering. Det ville være mest fornuftig for deg å studere Java Collections-oppdraget, som omhandler emner nær artikkelen.
Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2) - 1

Opprette enheter

I entities -pakken lager vi en Userklasse som har to private strengvariabler: navn og passord . Lag konstruktører (standard og en som tar begge verdiene) og gettere/settere, og overstyr metoden toString()for sikkerhets skyld, sammen med equals()og hashCode()metodene. Med andre ord, vi vil gjøre alt som en respektabel Java-utvikler gjør når de oppretter 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;
    }
}
Nå kan vi begynne å lage en liste over brukere. Vi legger til brukere til den, og tar brukere fra den for å vise dem. Vi har imidlertid ett problem. Vi lager ikke servlet-objektene våre. Tomcat gjør dette for oss. Metodene vi overstyrer i dem er allerede definert for oss, og vi kan ikke parametere. Hvordan lager vi da en delt liste som vil være synlig i begge servletene våre? Hvis vi bare oppretter et listeobjekt i hver servlet, vil vi legge til brukere til en liste, men vise brukere fra en annen i ListServlet. Så vi trenger et objekt som deles av begge servletene. Generelt sett trenger vi et objekt som deles av alle klassene i programmet vårt: ett objekt for hele programmet. Jeg håper du har hørt noe om designmønstre. For noen mennesker kan dette være det første virkelige behovet for Singleton- mønsteret i programmet deres. Du kan gå galt og skru ut litt søt Singleton med dobbeltsjekker og synkronisering (jepp, applikasjonen vår er flertrådet, siden Tomcat-servlets kjører på separate tråder). Men jeg kommer til å bruke den tidlige initialiseringsteknikken, fordi den er helt tilstrekkelig for våre formål her.

Å lage en modell

Lag en klasse (og implementer Singleton- mønsteret) i modellpakken og kall det noe uvanlig. For eksempel Model . Vi oppretter en privat liste over brukere i klassen vår, og implementerer to metoder: en for å legge til en bruker, og en annen for å returnere en liste med strenger (brukernavn). Siden brukerobjektet vårt består av et brukernavn og passord, og vi ikke ønsker å avsløre brukerpassord, har vi kun en liste med navn.

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

Litt om MVC

Siden du allerede har hørt om singleton , har du sannsynligvis hørt om en annen design pattern model-view-controller (MVC). Formålet er å skille forretningslogikk fra utsikten. Det vil si å skille koden som bestemmer hva som skal gjøres fra koden som bestemmer hvordan ting skal vises. Utsikten er ansvarlig for hvordan data presenteres. I vårt tilfelle er visningene våre JSP-sider . Det er nettopp derfor jeg legger dem i en mappe som heter views . Modellen er dataene programmet faktisk jobber med. I vårt tilfelle er dette brukerne (liste over brukere). Og kontrollere er bindeleddet mellom dem. De tar data fra modellen og sender dem til visningene (eller får noen data fra Tomcat, bearbeid den og send den til modellen). Du definerer forretningslogikken din (hva programmet skal gjøre) i dem, ikke i modellen eller visningen. Dermed håndterer hver del sin egen virksomhet:
  • modellen lagrer data;
  • visninger gir vakre representasjoner av dataene;
  • behandlingsansvarlige håndterer databehandling.
Dette gjør at programmet er ganske enkelt og vedlikeholdbart, i stedet for en monstrøs haug med all koden i én klasse. MVC er ikke bare egnet for webprogrammering, men det brukes spesielt ofte i dette området (nesten alltid). I vårt tilfelle vil servletene fungere som kontroller. Dette er en veldig overfladisk og kort beskrivelse av mønsteret, men MVC er ikke hovedtemaet i denne artikkelen. Hvis noen vil lære mer, er Google din venn! Lag et skjema for å legge til en bruker. Legg til skjemaet til add.jsp . Den skal bestå av to tekstinntastingsfelt (ett vanlig, det andre - et passordfelt) og en knapp for å sende dataene 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 skjemaet et metodeattributt med verdiposten . Dette indikerer at dataene fra dette skjemaet vil gå til serveren som en POST-forespørsel . Action - attributtet er ikke spesifisert, noe som betyr at forespørselen vil bli sendt til samme adresse som vi kom til denne siden fra ( /add ). Når vi mottar en GET-forespørsel , returnerer vår servlet bundet til denne adressen JSP-en med add-user-skjemaet. Og hvis den mottar en POST-forespørsel , vet vi at skjemaet sendte dataene sine her (som vi trekker ut fra forespørselsobjektet idoPost()metode, prosess og overgang til modellen for lagring). Det er verdt å merke seg at inndatafelt har en parameter kalt navn (for brukernavn, eller pass for passord). Dette er et veldig viktig poeng. For å motta disse dataene (brukernavnet og passordet som vil bli oppgitt) fra forespørselen (inne i servleten), bruker vi disse navn- og passfeltene . Men mer om det senere. Knappen min for å sende data ble igjen laget som en knapp , ikke som et utdatafelt slik det er vanlig. Jeg vet ikke hvor utbredt denne tilnærmingen er, men den fungerer for meg (Chrome-nettleseren).

Servlet-håndtering av POST-forespørsler

La oss gå tilbake til AddServlet . Jeg minner deg om at for å tillate vår servlet å "fange" GET-forespørsler , overstyrte vi doGet()metoden i HttpServlet- klassen. For å lære servleten vår å også fange POST-forespørsler , må vi også overstyre doPost()metoden. Tomcat sender den lignende forespørsels- og svarobjekter som vi skal jobbe med. For å starte, trekk ut forespørselens navn og pass parametere sendt av skjemaet (hvis du spesifiserte forskjellige navn i skjemaet, bruk disse navnene). Deretter oppretter du et brukerobjekt ved å bruke de mottatte dataene. Deretter henter vi modellobjektet og legger den opprettede brukeren 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

La oss gå videre til ListServlet . Metoden doGet()er allerede implementert. Den overfører ganske enkelt kontroll til visningen ( list.jsp ). Hvis du ikke har dette ennå, kan du lage det analogt med metoden i AddServlet . Nå ville det være fint å få listen over brukernavn fra modellen og sende dem til visningen, som vil motta dem og vise dem vakkert. For å gjøre dette vil vi igjen bruke forespørselsobjektet vi mottok fra Tomcat . Vi kan legge til et attributt til dette objektet, og gi det et slags navn. Faktisk kan vi legge til objektet vi vil sende til visningen. På grunn av det faktum at når vi overfører kontroll fra servleten til visningen, sender vi visningen de samme forespørsels- og svarobjektene som servleten mottok, kan vi legge til vår liste over navn til forespørselsobjektet og deretter hente listen over brukernavn fra forespørselen objekt i visningen. Vi er ferdige med ListServlet- klassen, så jeg presenterer 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);
    }
}

Kjører Java-kode i JSP-filer

Det er på tide å se på list.jsp . Den vil bare bli utført når ListServlet overfører kontrollen til den. I tillegg har vi allerede forberedt listen over brukernavn fra modellen i servleten og sendt den her i forespørselsobjektet. Siden vi har listen over navn, kan vi iterere over den ved å bruke en forløkke og vise hvert navn. Som jeg sa før, kan JSP-filer kjøre Java-kode (som er det som skiller dem fra statiske HTML-sider). For å utføre noe kode, er alt vi trenger å gjøre å sette følgende konstruksjon på riktig sted:

<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Innenfor denne konstruksjonen får vi tilgang til flere variabler:
  • request — our request object, som vi sendte fra servleten, hvor det ganske enkelt ble kalt req ;
  • response — responsobjektet (kalt resp i servleten);
  • out — et JspWriter- objekt (som arver en vanlig Writer ), som vi kan bruke til å "skrive" noe direkte inn i selve HTML-siden . Utsagnet out.println("Hello, World!") ligner veldig på System.out.println("Hello, World!") , men ikke forveksle dem!
  • out.println() "skriver" til en HTML-side , mens System.out.println skriver til systemets utdatastrøm . Hvis du kaller System.out.println() i en JSP- seksjon med Java-kode , vil du se resultatene i Tomcat -konsollen, men ikke på siden.
Du kan se etter andre objekter som er tilgjengelige i en JSP her . Vi kan bruke forespørselsobjektet for å få listen over navn sendt fra servleten (vi har knyttet den tilsvarende attributten til dette objektet), og vi får bruke ut objektet for å vise disse navnene. La oss vise dem (foreløpig som en enkel 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 bare trenger å vise listen hvis det er brukere, og ellers vise en advarsel om at det ikke er noen brukere ennå, kan vi omskrive denne delen litt:

<%
    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>");
%>
Nå som vi vet hvordan vi overfører data fra servlets til visninger, kan vi forbedre AddServleten vår slik at den viser et varsel om vellykket tillegg av en bruker. For å gjøre dette, i doPost()metoden, etter å ha lagt til en ny bruker til modellen, kan vi legge til dette brukernavnet til req- objektets attributter og sende kontrollen tilbake til en visning ( add.jsp ). Og nå vil vi legge til en seksjon med Java-kode til den, der vi vil sjekke om forespørselen har et slikt attributt, og hvis det gjør det - så vil vi vise en melding om at brukeren ble lagt til. Etter disse endringene vil AddServlets fullstendige kode se omtrent slik ut:

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, på slutten av metoden, doPost()oppretter vi et attributt med navnet på brukeren som ble lagt til modellen, og kaller deretter metoden, doGet()som vi sender den gjeldende forespørselen og svaret til. Metoden doGet()overfører nå kontroll til visningen, som også mottar forespørselsobjektet med navnet på den lagte brukeren vedlagt som attributt. Det som gjenstår for oss å gjøre er å fikse add.jsp slik at den viser varselet hvis det ikke finnes et slikt attributt. Her er den endelige versjonen av 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 av følgende:
  • en div med en overskrift;
  • en div-beholder for innhold, som inkluderer en sjekk om det finnes et attributt med et brukernavn;
  • en div med add-user-skjemaet;
  • og nederst en bunntekst med en knapp for å gå tilbake til startsiden.
Dette kan virke som for mange divs, men vi bruker dem senere når vi legger til stiler. Her er den endelige versjonen av 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>
Dermed har vi en fullt fungerende webapplikasjon som kan lagre og legge til brukere, og også vise en liste over navnene deres. Nå må vi bare gjøre det pent... :) Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2) - 2

Legge til stiler. Vi bruker rammeverket W3.CSS

For øyeblikket fungerer applikasjonen vår, men den ser helt opprørende ut. Så la oss legge til en bakgrunn, fargelegge teksten og knappene, legge til stil på listene, justere elementer, legge til innrykk, og så videre. Å skrive stiler manuelt kan ta mye tid og belaste nervene våre. Så jeg foreslår å bruke W3.CSS- rammeverket. Den har allerede klare til bruk klasser med stiler. Vi trenger bare å ordne CSS-klassene vi ønsker å bruke på de riktige stedene. For å legge dem til sidene våre, kobler vi først til stilfilen. Det er to måter å gjøre dette på:
  1. gå gjennom sidene våre og legg inn følgende direkte lenke til stilfilen i head-delen

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

    Dette alternativet passer hvis du har en permanent Internett-tilkobling. Når du åpner sidene dine på den lokale serveren, vil stilene bli hentet fra Internett.

  2. Men hvis du vil ha alle stilene lokalt og ikke er avhengig av en Internett-tilkobling, last ned stilfilen og plasser den et sted inne i webmappen ( f.eks. web/styles/w3.css ). Gå deretter gjennom alle sidene våre ( index.html, add.jsp, list.jsp ) og legg til følgende lenke til stilfilen i head- delen:

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

    Etter det er det bare å gå gjennom kodene og legge til stilene du liker. Jeg vil ikke dvele ved dette i detalj. I stedet vil jeg bare gi ferdige versjoner av tre av filene mine med raster-stilklasser.

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 fortsatt har spørsmål eller kommentarer, eller hvis noe ikke fungerer, vennligst legg igjen en kommentar. Og jeg legger ved et par skjermbilder av hvordan det hele ble.
Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2) - 3
Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2) - 4
Opprette en enkel nettapplikasjon ved hjelp av servlets og JSP-er (del 2) - 5
Og til slutt , hvis du vil øve med dette prosjektet, kan du prøve følgende:
  • lag en servlet og JSP for å slette en bruker, og legg til et annet par for å redigere en eksisterende bruker. Resultatet vil være en ekte CRUD-nettapplikasjon bygget ved hjelp av servlets. ;)
  • erstatte listen med en database, slik at de tilførte brukerne ikke forsvinner etter at serveren er startet på nytt. :)
Lykke til!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION