
Entitások létrehozása
Az entitások csomagban létrehozunk egyUser
osztályt, amely két privát karakterlánc-változóval rendelkezik: név és jelszó . Hozzon létre konstruktorokat (alapértelmezett és egyet, amely mindkét értéket felveszi) és gettereket/beállítókat, és minden esetre felülírja a metódust a és metódusokkal toString()
együtt . Más szóval, mindent megteszünk, amit egy tekintélyes Java fejlesztő tesz az osztály létrehozásakor. equals()
hashCode()
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;
}
}
Most elkezdhetjük létrehozni a felhasználók listáját. Hozzáadunk hozzá felhasználókat, és kiveszünk belőle felhasználókat, hogy megjelenítsük őket. Van azonban egy problémánk. Nem mi hozzuk létre a szervlet objektumokat. A Tomcat megteszi ezt helyettünk. A bennük felülírt metódusok már definiáltak számunkra, és nem tudunk paraméterezni. Hogyan hozzunk létre egy megosztott listát, amely mindkét szervletben látható lesz? Ha csak egy listaobjektumot hozunk létre minden szervletben, akkor a felhasználókat az egyik listához adnánk, de a ListServletben megjelenítenénk a másikat .. Tehát szükségünk van egy objektumra, amelyet mindkét szervlet megoszt. Általánosságban elmondható, hogy szükségünk van egy objektumra, amelyet a programunk összes osztálya megoszt: egy objektum a teljes programhoz. Remélem hallottál valamit a tervezési mintákról. Néhány ember számára ez lehet az első igazi igény a Singleton mintára a programjukban. Elkezdhetsz valami édes Singletont dupla ellenőrzéssel és szinkronizálással (igen, az alkalmazásunk többszálú, mivel a Tomcat szervletek külön szálakon futnak). De én a korai inicializálási technikát fogom használni, mert ez teljesen megfelel a mi céljainknak.
Modell készítése
Hozzon létre egy osztályt (és valósítsa meg a Singleton mintát) a modellcsomagban , és nevezze valami szokatlannak. Például a Modell . Létrehozunk egy privát listát az osztályunkban lévő felhasználókról, és két módszert alkalmazunk: az egyiket a felhasználó hozzáadására, a másikat pedig a karakterláncok (felhasználónevek) listájának visszaadására. Mivel felhasználói objektumunk egy felhasználónévből és egy jelszóból áll, és nem akarjuk felfedni a felhasználói jelszavakat, csak a nevek listája lesz.
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());
}
}
Egy kicsit az MVC-ről
Mivel már hallott a singletonról , valószínűleg hallott egy másik tervezési minta -modell-nézet-vezérlőről (MVC). Célja az üzleti logika és a nézet elkülönítése. Vagyis elkülöníteni a teendőket meghatározó kódot a dolgok megjelenítését meghatározó kódtól. A nézet felelős az adatok bemutatásáért. Esetünkben a nézetek a JSP-oldalaink . Pontosan ezért tettem őket egy view nevű mappába . A modell azok az adatok, amelyekkel a program ténylegesen dolgozik. Esetünkben ez a felhasználók (felhasználók listája). És a vezérlők jelentik a kapcsolatot közöttük. Adatokat vesznek a modellből, és továbbítják a nézeteknek (vagy kapnak néhány adatot a Tomcattől, dolgozza fel, és adja át a modellnek). Ezekben határozza meg az üzleti logikáját (mit kell tennie a programnak), nem a modellben vagy a nézetben. Így minden rész a saját dolgát intézi:- a modell adatokat tárol;
- a nézetek gyönyörűen ábrázolják az adatokat;
- adatkezelők kezelik az adatkezelést.
<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>
Itt az űrlapnak van egy method attribútuma post értékkel . Ez azt jelzi, hogy az űrlap adatai POST-kérésként fognak eljutni a szerverhez . Az action attribútum nincs megadva, ami azt jelenti, hogy a kérés ugyanarra a címre kerül elküldésre, ahonnan erre az oldalra érkeztünk ( /add ). Így a GET kérés fogadásakor az ehhez a címhez kötött szervletünk visszaadja a JSP-t az add-user űrlappal. És ha POST kérést kap , akkor tudjuk, hogy az űrlap elküldte ide az adatait (amit a kérés objektumból nyerünk ki adoPost()
módszer, folyamat, és adja át a modellnek mentésre). Érdemes megjegyezni, hogy a beviteli mezőknek van egy név nevű paramétere (felhasználónevekhez vagy jelszavakhoz pass ). Ez egy nagyon fontos szempont. Ezért, hogy megkapjuk ezeket az adatokat (a beírandó felhasználónév és jelszó) a kérésből (a szervleten belül), ezeket a név- és jelmezőket használjuk . De erről majd később. Az adatküldő gombom ismét gombnak készült , nem pedig kimeneti mezőnek, ahogy az lenni szokott. Nem tudom, milyen széles körben alkalmazzák ezt a megközelítést, de nálam működik (Chrome böngésző).
POST kérések szervlet kezelése
Térjünk vissza az AddServlethez . Emlékeztetjük, hogy annak érdekében, hogy a servletünk "elfoghassa" a GET kéréseket , felülírtukdoGet()
a HttpServlet osztály metódusát. Ahhoz, hogy megtanítsuk a szervletünket a POST kérések elkapására is , felül kell bírálnunk a doPost()
metódust. A Tomcat hasonló kérés- és válaszobjektumokat ad át neki, amelyekkel dolgozni fogunk. Kezdésként bontsa ki a kérés nevét és adja át az űrlap által küldött paramétereket (ha eltérő neveket adott meg az űrlapon, akkor használja ezeket a neveket). Ezután hozzon létre egy felhasználói objektumot a kapott adatok felhasználásával. Ezután megkapjuk a modell objektumot, és hozzáadjuk a létrehozott felhasználót a modellhez.
@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);
}
Adatok továbbítása a nézetbe
Térjünk át a ListServlet-re . AdoGet()
módszer már megvalósult. Egyszerűen átadja a vezérlést a nézetre ( list.jsp ). Ha még nem rendelkezik ezzel, akkor hozza létre az AddServlet metódusával analóg módon . Most jó lenne a modell felhasználóneveinek listáját átadni a nézetnek, amely megkapja és gyönyörűen megjeleníti őket. Ehhez ismét a Tomcattől kapott kérelem objektumot fogjuk használni . Hozzáadhatunk egy attribútumot ehhez az objektumhoz, valamilyen nevet adva neki. Valójában az átadni kívánt objektumot hozzáadhatjuk a nézethez. Tekintettel arra, hogy amikor a servletről a nézetre átadjuk a vezérlést, ugyanazokat a kérés és válasz objektumokat adjuk át a nézetnek, mint amit a servlet kapott, a kérés objektumhoz hozzáadhatjuk a névlistánkat, majd lekérhetjük a felhasználónevek listáját a kérésből. tárgy a nézetben. Elkészültünk a ListServlet osztállyal, így itt bemutatom a teljes osztály kódját:
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);
}
}
Java kód futtatása JSP fájlokban
Ideje megnézni a list.jsp fájlt . Csak akkor kerül végrehajtásra, ha a ListServlet átadja neki az irányítást. Ezenkívül a servletben már elkészítettük a modellből a felhasználónevek listáját, és átadtuk ide a request objektumban. Mivel megvan a nevek listája, ismételhetünk rajta egyfor
ciklus segítségével, és megjeleníthetjük az egyes neveket. Ahogy korábban mondtam, a JSP fájlok képesek Java kódot futtatni (ez különbözteti meg őket a statikus HTML oldalaktól). Egy kód futtatásához nem kell mást tennünk, mint a következő konstrukciót a megfelelő helyre tenni:
<!-- html code -->
<%
// Java code
%>
<!-- html code -->
Ezen a konstrukción belül több változóhoz is hozzáférünk:
- request — a kérés objektumunk, amelyet a szervletből adtunk át, ahol egyszerűen req-nek hívták ;
- válasz — a válaszobjektum ( resp a szervletben);
- out — egy JspWriter objektum (amely egy közönséges Writer-t örököl ), amellyel közvetlenül magába a HTML oldalra tudunk "írni" valamit . Az out.println("Hello, World!") kijelentés nagyon hasonlít a System.out.println("Hello, World!") kifejezésre , de ne keverje össze őket!
- Az out.println() "ír" egy HTML oldalra , míg a System.out.println a rendszer kimeneti adatfolyamába ír . Ha a System.out.println() függvényt egy Java kóddal rendelkező JSP szakaszon belül hívja meg , az eredményeket látni fogja a Tomcat konzolon, de nem az oldalon.
<ul>
<%
List<String> names = (List<String>) request.getAttribute("userNames");
if (names != null && !names.isEmpty()) {
for (String s : names) {
out.println("<li>" + s + "</li>");
}
}
%>
</ul>
Ha csak akkor kell megjelenítenünk a listát, ha vannak felhasználók, egyébként pedig figyelmeztetést jelenítünk meg, hogy még nincsenek felhasználók, akkor ezt a részt kicsit átírhatjuk:
<%
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>");
%>
Most, hogy tudjuk, hogyan lehet adatokat átadni a servletekből a nézeteknek, továbbfejleszthetjük AddServletünket úgy , hogy értesítést jelenítsen meg a felhasználó sikeres felvételéről. Ehhez a doPost()
metódusban, miután új felhasználót adtunk a modellhez, hozzáadhatjuk ezt a felhasználónevet a req objektum attribútumaihoz, és visszaadhatjuk a vezérlést egy nézetnek ( add.jsp ). És most adunk hozzá egy Java kóddal ellátott részt, ahol ellenőrizzük, hogy a kérés rendelkezik-e ilyen attribútummal, és ha igen, akkor egy üzenetet jelenítünk meg, amely szerint a felhasználó sikeresen hozzáadva. A változtatások után az AddServlet teljes kódja így fog kinézni:
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);
}
}
Itt a metódus végén doPost()
létrehozunk egy attribútumot a modellbe felvett felhasználó nevével, majd meghívjuk a doGet()
metódust, aminek átadjuk az aktuális kérést és választ. A doGet()
metódus most átadja az irányítást a nézetnek, amely a felvett felhasználó nevével attribútumként csatolt kérelem objektumot is megkapja. Továbbra is ki kell javítanunk az add.jsp fájlt , hogy megjelenítse az értesítést, ha nincs ilyen attribútum. Íme az add.jsp végleges verziója :
<%@ 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>
Az oldal törzse a következőkből áll:
- egy div fejléccel;
- div konténer a tartalomhoz, amely magában foglalja annak ellenőrzését, hogy létezik-e felhasználónévvel rendelkező attribútum;
- div az add-user űrlappal;
- alul pedig egy lábléc egy gombbal a kezdőlapra való visszatéréshez.
<%@ 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>
Így van egy teljesen működő webes alkalmazásunk, amely képes menteni és hozzáadni felhasználókat, valamint megjeleníteni egy listát a nevükről. Most már csak szépíteni kell... :) 
Stílusok hozzáadása. A W3.CSS keretrendszert fogjuk használni
Jelenleg az alkalmazásunk működik, de teljesen felháborítónak tűnik. Tehát adjunk hozzá hátteret, színezzük ki a szöveget és a gombokat, adjunk stílust a listákhoz, igazítsuk el az elemeket, adjunk hozzá behúzásokat és így tovább. A stílusok kézi írása sok időt vehet igénybe, és megterhelheti az idegeinket. Ezért a W3.CSS keretrendszer használatát javaslom . Már vannak használatra kész osztályai stílusokkal. Csak a megfelelő helyekre kell rendeznünk a használni kívánt CSS osztályokat. Ahhoz, hogy hozzáadjuk őket oldalainkhoz, először csatlakoztatjuk a stílusfájlt. Ennek két módja van:-
menjen végig oldalainkon, és illessze be a következő közvetlen hivatkozást a stílusfájlra a fejrészbe
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
Ez az opció akkor megfelelő, ha állandó internetkapcsolattal rendelkezik. Amikor megnyitja oldalait a helyi szerveren, a stílusok az internetről származnak.
-
De ha azt szeretné, hogy az összes stílus helyben legyen, és ne függjön az internetkapcsolattól, töltse le a stílusfájlt, és helyezze el valahová a webmappán belül ( pl. web/styles/w3.css ). Ezután menjen végig az összes oldalunkon ( index.html, add.jsp, list.jsp ), és adja hozzá a következő hivatkozást a stílusfájlhoz a fejrészen belül :
<link rel="stylesheet" href="styles/w3.css">
Ezután csak menjen át a címkéken, és adja hozzá a kívánt stílusokat. Nem részletezem ezt. Ehelyett három fájlom használatra kész verzióját biztosítom raszter stílusú osztályokkal.
<!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>
És ez az. :) Ha van még kérdésed, észrevételed, esetleg valami nem sikerül, írj kommentet. És csatolok pár képernyőképet, hogy hogyan is alakult az egész.



- hozzon létre egy szervletet és egy JSP-t egy felhasználó törléséhez, és adjon hozzá egy másik párt egy meglévő felhasználó szerkesztéséhez. Az eredmény egy valódi CRUD webalkalmazás lesz, amely szervletek felhasználásával készül. ;)
- cserélje ki a Listát egy adatbázisra, hogy a hozzáadott felhasználók ne tűnjenek el a kiszolgáló újraindítása után. :)
GO TO FULL VERSION