CodeGym /Java blogg /Slumpmässig /Skapa en enkel webbapplikation med servlets och JSP:er (d...
John Squirrels
Nivå
San Francisco

Skapa en enkel webbapplikation med servlets och JSP:er (del 2)

Publicerad i gruppen
Skapa en enkel webbapplikation med hjälp av servlets och JSP:er (del 1) Kunskaper som krävs för att förstå artikeln: Du har redan mer eller mindre räknat ut Java Core och skulle vilja titta på JavaEE-teknologier och webbprogrammering. Det skulle vara mest meningsfullt för dig att för närvarande studera Java Collections-uppdraget, som handlar om ämnen nära artikeln.
Skapa en enkel webbapplikation med servlets och JSP:er (del 2) - 1

Skapar enheter

I entities -paketet skapar vi en Userklass som har två privata strängvariabler: namn och lösenord . Skapa konstruktörer (standard och en som tar båda värdena) och getters/setters, och åsidosätt metoden toString()för säkerhets skull, tillsammans med equals()och hashCode()metoderna. Med andra ord kommer vi att göra allt som en respektabel Java-utvecklare gör när vi skapar en klass.

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 börja skapa en lista över användare. Vi lägger till användare till den och tar användare från den för att visa dem. Vi har dock ett problem. Vi skapar inte våra servletobjekt. Tomcat gör detta åt oss. De metoder vi åsidosätter i dem är redan definierade för oss, och vi kan inte parametrar. Hur skapar vi då en delad lista som kommer att synas i båda våra servlets? Om vi ​​bara skapar ett listobjekt i varje servlet, så skulle vi lägga till användare till en lista, men visa användare från en annan i ListServlet. Så vi behöver ett objekt som delas av båda servletarna. Generellt sett behöver vi ett objekt som delas av alla klasser i vårt program: ett objekt för hela programmet. Jag hoppas att du har hört något om designmönster. För vissa människor kan detta vara det första verkliga behovet av Singleton- mönstret i deras program. Du kan gå galet och veva ut lite söt Singleton med dubbelkontroller och synkronisering (ja, vår applikation är flertrådad, eftersom Tomcat-servlets körs på separata trådar). Men jag kommer att använda den tidiga initieringstekniken, eftersom den är helt tillräcklig för våra syften här.

Att skapa en modell

Skapa en klass (och implementera Singleton- mönstret) i modellpaketet och kalla det något ovanligt. Till exempel Model . Vi skapar en privat lista över användare i vår klass och implementerar två metoder: en för att lägga till en användare och en annan för att returnera en lista med strängar (användarnamn). Eftersom vårt användarobjekt består av ett användarnamn och lösenord, och vi inte vill avslöja användarlösenord, kommer vi bara att ha en lista med namn.

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

Lite om MVC

Eftersom du redan har hört talas om singleton har du förmodligen hört talas om en annan design pattern model-view-controller ( MVC). Dess syfte är att skilja affärslogik från synen. Det vill säga att separera koden som bestämmer vad som ska göras från koden som bestämmer hur saker ska visas. Vyn ansvarar för hur data presenteras . I vårt fall är åsikterna våra JSP-sidor . Det är just därför jag lägger dem i en mapp som heter views . Modellen är den data som programmet faktiskt arbetar med. I vårt fall är detta användarna (listan över användare). Och kontroller är länken mellan dem. De tar data från modellen och skickar den till vyerna (eller får lite data från Tomcat, bearbeta det och skicka det till modellen). Du definierar din affärslogik (vad programmet ska göra) i dem, inte i modellen eller vyn. Således sköter varje del sin egen verksamhet:
  • modellen lagrar data;
  • vyer ger vackra representationer av data;
  • registeransvariga hanterar databehandling.
Detta gör att programmet är ganska enkelt och underhållbart, snarare än en monstruös hög med all kod i en klass. MVC lämpar sig inte bara för webbprogrammering, utan det används särskilt ofta inom detta område (nästan alltid). I vårt fall kommer servletarna att fungera som kontroller. Detta är en mycket ytlig och kort beskrivning av mönstret, men MVC är inte huvudämnet i denna artikel. Om någon vill veta mer är Google din vän! Skapa ett formulär för att lägga till en användare. Lägg till formuläret till add.jsp . Det bör bestå av två textinmatningsfält (ett vanligt, det andra - ett lösenordsfält) och en knapp för att skicka data till servern.

<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>
Här har formuläret ett metodattribut med värdeposten . Detta indikerar att data från detta formulär kommer att gå till servern som en POST-förfrågan . Action - attributet är inte specificerat, vilket innebär att begäran kommer att skickas till samma adress som vi kom till den här sidan från ( / add ) . Sålunda, vid mottagande av en GET-begäran , returnerar vår servlet bunden till denna adress JSP:n med add-user-formuläret. Och om den tar emot en POST-begäran vet vi att formuläret skickade dess data hit (som vi extraherar från begäranobjektet idoPost()metod, process och övergång till modellen för att spara). Det är värt att notera att inmatningsfälten har en parameter som heter namn (för användarnamn, eller pass för lösenord). Detta är en mycket viktig punkt. För att ta emot dessa data (användarnamnet och lösenordet som kommer att anges) från begäran (inuti servleten), kommer vi att använda dessa namn- och lösenordsfält . Men mer om det senare. Min knapp för att skicka data gjordes återigen som en knapp , inte som ett utdatafält som är vanligt. Jag vet inte hur utbrett det här tillvägagångssättet är, men det fungerar för mig (Chrome-webbläsaren).

Servlet-hantering av POST-förfrågningar

Låt oss återgå till AddServlet . Jag påminner dig om att för att tillåta vår servlet att "fånga" GET-förfrågningar , åsidosatte vi doGet()metoden i klassen HttpServlet . För att lära vår servlet att även fånga POST-förfrågningar måste vi också åsidosätta doPost()metoden. Tomcat skickar liknande förfrågnings- och svarsobjekt som vi kommer att arbeta med. För att börja, extrahera begärans namn och skicka parametrar som skickas av formuläret (om du angav olika namn i formuläret, använd sedan dessa namn). Därefter skapar du ett användarobjekt med hjälp av mottagna data. Sedan hämtar vi modellobjektet och lägger till den skapade användaren i 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);
}

Skickar data till vyn

Låt oss gå vidare till ListServlet . Metoden doGet()är redan implementerad. Den överför helt enkelt kontrollen till vyn ( list.jsp ) . Om du inte har detta ännu, skapa det i analogi med metoden i AddServlet . Nu skulle det vara trevligt att få listan med användarnamn från modellen och skicka dem till vyn, som tar emot dem och visar dem vackert. För att göra detta kommer vi återigen att använda förfrågningsobjektet vi fick från Tomcat . Vi kan lägga till ett attribut till detta objekt och ge det något slags namn. Faktum är att vi kan lägga till objektet vi vill skicka till vyn. På grund av det faktum att när vi överför kontroll från servleten till vyn skickar vi vyn samma förfrågnings- och svarsobjekt som servleten fick, kan vi lägga till vår namnlista till förfrågningsobjektet och sedan hämta vår lista med användarnamn från förfrågan objekt i vyn. Vi är klara med ListServlet- klassen, så jag kommer att presentera koden för hela klassen här:

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ör Java-kod i JSP-filer

Det är dags att titta på list.jsp . Den kommer bara att köras när ListServlet överför kontrollen till den. Dessutom har vi redan förberett listan med användarnamn från modellen i servleten och skickat den här i förfrågningsobjektet. Eftersom vi har listan med namn kan vi iterera över den med en forloop och visa varje namn. Som jag sa tidigare kan JSP-filer köra Java-kod (vilket är det som skiljer dem från statiska HTML-sidor). För att exekvera någon kod behöver vi bara sätta följande konstruktion på lämplig plats:

<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Inom denna konstruktion får vi tillgång till flera variabler:
  • request — our request object, som vi skickade från servleten, där det helt enkelt hette req ;
  • response — responsobjektet (kallas resp i servleten);
  • out — ett JspWriter- objekt (som ärver ett vanligt Writer ), som vi kan använda för att "skriva" något direkt i själva HTML-sidan . Uttalandet out.println("Hello, World!") är väldigt likt System.out.println("Hello, World!") , men förväxla dem inte!
  • out.println() "skriver" till en HTML-sida medan System.out.println skriver till systemets utdataström . Om du anropar System.out.println() inom en JSP- sektion med Java-kod , kommer du att se resultaten i Tomcat -konsolen, men inte på sidan.
Du kan leta efter andra objekt som är tillgängliga inom en JSP här . Vi kan använda request -objektet för att få listan med namn som skickas från servleten (vi bifogade motsvarande attribut till detta objekt), och vi får använda out- objektet för att visa dessa namn. Låt oss visa dem (för närvarande som en enkel HTML-lista):

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

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
Om vi ​​bara behöver visa listan om det finns användare, och annars visa en varning om att det inte finns några användare ännu, kan vi skriva om det här avsnittet lite:

<%
    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 när vi vet hur man skickar data från servlets till vyer kan vi förbättra vår AddServlet så att den visar ett meddelande om framgångsrikt tillägg av en användare. För att göra detta, i doPost()metoden, efter att ha lagt till en ny användare till modellen, kan vi lägga till detta användarnamn till req -objektets attribut och skicka tillbaka kontrollen till en vy ( add.jsp ). Och nu lägger vi till en sektion med Java-kod till den, där vi kontrollerar om begäran har ett sådant attribut, och om den gör det - då visar vi ett meddelande om att användaren har lagts till. Efter dessa ändringar kommer AddServlets fullständiga kod att se ut ungefär så här:

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);
    }
}
Här, i slutet av doPost()metoden, skapar vi ett attribut med namnet på användaren som lades till i modellen, och anropar sedan metoden, doGet()till vilken vi skickar den aktuella begäran och svaret. Metoden doGet()överför nu kontrollen till vyn, som också tar emot förfrågningsobjektet med namnet på den tillagda användaren bifogat som attribut. Det som återstår för oss att göra är att fixa add.jsp så att den visar meddelandet om det inte finns något sådant attribut. Här är den slutliga versionen 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>
Sidans brödtext består av följande:
  • en div med en rubrik;
  • en div-behållare för innehåll, som inkluderar en kontroll om det finns ett attribut med ett användarnamn;
  • en div med add-user-formuläret;
  • och längst ner en sidfot med en knapp för att återgå till startsidan.
Det här kan verka som för många div, men vi kommer att använda dem senare när vi lägger till stilar. Här är den slutliga versionen 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>
Således har vi en fullt fungerande webbapplikation som kan spara och lägga till användare, och även visa en lista med deras namn. Nu ska vi bara göra det snyggt... :) Skapa en enkel webbapplikation med servlets och JSP:er (del 2) - 2

Lägga till stilar. Vi kommer att använda ramverket W3.CSS

För tillfället fungerar vår applikation, men den ser helt upprörande ut. Så låt oss lägga till en bakgrund, färglägga texten och knapparna, lägga till stil i listorna, justera element, lägga till indrag och så vidare. Att skriva stilar manuellt kan ta mycket tid och belasta våra nerver. Så jag föreslår att du använder ramverket W3.CSS . Den har redan färdiga klasser med stilar. Vi behöver bara ordna de CSS-klasser vi vill använda på rätt ställen. För att lägga till dem på våra sidor ansluter vi först stilfilen. Det finns två sätt att göra detta:
  1. gå igenom våra sidor och infoga följande en direktlänk till stilfilen i rubriken

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

    Det här alternativet är lämpligt om du har en permanent Internetanslutning. När du öppnar dina sidor på den lokala servern kommer stilarna att hämtas från Internet.

  2. Men om du vill ha alla stilar lokalt och inte är beroende av en Internetanslutning, ladda ner stilfilen och placera den någonstans i webbmappen ( t.ex. web /styles/w3.css ) . Gå sedan igenom alla våra sidor ( index.html, add.jsp, list.jsp ) och lägg till följande länk till stilfilen i huvudsektionen :

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

    Efter det går du bara igenom taggarna och lägger till de stilar du gillar. Jag ska inte gå in på detta i detalj. Istället kommer jag bara att tillhandahålla färdiga versioner av tre av mina filer med rasterliknande 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>
Och det är allt. :) Om du fortfarande har några frågor eller kommentarer, eller om något inte fungerar, lämna gärna en kommentar. Och jag bifogar ett par skärmdumpar på hur det hela blev.
Skapa en enkel webbapplikation med servlets och JSP:er (del 2) - 3
Skapa en enkel webbapplikation med servlets och JSP:er (del 2) - 4
Skapa en enkel webbapplikation med servlets och JSP:er (del 2) - 5
Och slutligen , om du vill öva med det här projektet, kan du prova följande:
  • gör en servlet och JSP för att ta bort en användare, och lägg till ytterligare ett par för att redigera en befintlig användare. Resultatet blir en äkta CRUD-webbapplikation byggd med servlets. ;)
  • ersätt listan med en databas, så att de tillagda användarna inte försvinner efter att servern har startat om. :)
Lycka till!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION