JavaRush /Blog Java /Random-PL /Tworzenie prostej aplikacji internetowej z wykorzystaniem...
fatfaggy
Poziom 26
Киев

Tworzenie prostej aplikacji internetowej z wykorzystaniem serwletów i jsp (część 2)

Opublikowano w grupie Random-PL
W dalszym ciągu opisuję proces tworzenia aplikacji internetowej z wykorzystaniem serwletów, jsp, Mavena i Tomcata. Początek artykułu , jeśli to konieczne.
Tworzymy podmioty.
Stwórzmy w pakiecie encji klasę User, w której utworzymy dwie prywatne zmienne typu string name i hasło. Stwórzmy konstruktory (domyślny i taki, który akceptowałby obie wartości), gettery/settery, na wszelki wypadek przesłońmy metodę toString() oraz metody równości() i 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; } } Teraz możemy przystąpić do tworzenia listy użytkowników, do której dodamy naszych użytkowników i skąd będziemy ich zabierać do wyświetlenia. Ale jest problem. Nie tworzymy naszych obiektów serwletów; Tomcat tworzy je za nas. Metody, które w nich nadpisujemy, również są już dla nas zdefiniowane i nie możemy dodać parametru. Jak zatem możemy stworzyć wspólną listę, która byłaby widoczna w obu naszych serwletach? Jeśli po prostu w każdym serwlecie utworzymy własny obiekt listowy, okaże się, że będziemy dodawać użytkowników do jednej listy, ale wyświetlanie listy użytkowników za pomocą serwletu ListServlet będzie zupełnie inne. Okazuje się, że potrzebujemy obiektu, który byłby wspólny dla obu serwletów. Ogólnie rzecz biorąc, potrzebujemy obiektu, który byłby wspólny dla wszystkich klas w naszym programie; jedyny obiekt dla całego programu. Mam nadzieję, że słyszałeś coś o wzorcach projektowych. I być może dla niektórych jest to pierwsza realna potrzeba wykorzystania szablonu Singleton w swoim programie. Można wykazać się kreatywnością i stworzyć fajny singleton z podwójnym sprawdzaniem i synchronizacją (tak, mamy aplikację wielowątkową, ponieważ Tomcat uruchamia serwlety w różnych wątkach), ale ja skorzystam z opcji z wczesną inicjalizacją, ponieważ w tym przypadku całkiem odpowiedni.
Tworzenie modelu.
Następnie utworzymy klasę (i zaimplementujemy w niej szablon singletonu) w pakiecie modelu, a także nazwiemy ją dość kolorowo Model. Stwórzmy w nim prywatny obiekt listy użytkowników i wykonajmy dwie metody: jedną, dzięki której będziesz mógł dodać użytkownika, a drugą - niech po prostu zwróci listę ciągów znaków (nazw użytkowników). Ponieważ nasz obiekt użytkownika składa się z nazwy i hasła, nie chcielibyśmy „ujawniać” haseł użytkowników, dlatego zwrócimy jedynie listę ich nazw. public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
Trochę o mvc.
Skoro słyszałeś o singletonie, oznacza to, że prawdopodobnie słyszałeś o innym wzorcu projektowym - MVC (kontroler widoku modelu lub po rosyjsku kontroler widoku modelu lub po prostu jak w języku angielskim kontroler widoku modelu). Jego istotą jest oddzielenie logiki biznesowej od prezentacji. Oznacza to, że oddziel kod określający, co zrobić, od kodu, który określa sposób wyświetlania . Widok (widok lub po prostu widoki) odpowiada za formę, w jakiej prezentowane są niektóre dane. W naszym przypadku widoki to nasze strony JSP. Dlatego umieściłem je w folderze o nazwie widoki. Model to rzeczywiste dane, z którymi program współpracuje. W naszym przypadku są to użytkownicy (lista użytkowników). Cóż, kontrolery są ogniwem łączącym między nimi. Pobierają dane z modelu i przesyłają je do widoków lub otrzymują pewne dane od Tomcata, przetwarzają je i przesyłają do modelu. Logikę biznesową (czyli co robić ) należy w nich opisać, a nie w modelu czy w widoku. Zatem każdy robi swoje:
  • model przechowuje dane
  • Widoki stanowią piękną reprezentację danych
  • administratorzy przetwarzają dane
Dzięki temu wszystkie są dość proste i łatwe w utrzymaniu. I nie jest to monstrualny zrzut całego kodu w jednej klasie. MVC nadaje się nie tylko do programowania w Internecie, ale nadal jest bardzo powszechny (jeśli nie zawsze) w tym obszarze. W naszym przypadku serwlety będą pełnić rolę kontrolerów. Tak, to bardzo powierzchowny i wręcz zgrubny opis tego wzorca, ale w tym artykule nie chodzi o wzorce projektowe, ale o to, jak zrobić prostą aplikację internetową :) Kto chce wiedzieć więcej – Google wie wszystko ! :) Wróćmy do naszych poglądów.
Utwórz formularz dodawania użytkownika.
Dodajmy do pliku add.jsp formularz składający się z dwóch wejść tekstowych (jeden zwykły, drugi typu hasło) oraz przycisku służącego do wysyłania danych na serwer. Tutaj formularz ma atrybut metody z wpisem wartości. Oznacza to, że dane z tego formularza zostaną przesłane na serwer w formie żądania POST. Atrybut akcji nie jest określony, co oznacza, że ​​to żądanie trafi na ten sam adres, z którego weszliśmy na tę stronę (/add). Zatem nasz serwlet powiązany z tym adresem po otrzymaniu żądania GET zwraca ten jsp z formularzem dodawania użytkowników, a jeśli otrzyma żądanie POST, to formularz ten wysłał tam swoje dane (które pobierzemy z obiekt żądania w metodzie doPost(), przetworzyć go i przesłać do modelu w celu zapisania). Warto zaznaczyć, że wejścia posiadają tutaj parametr name (dla pola z nazwą ma to nazwę wartości, a dla pola z hasłem wartość pass). To dość ważny punkt. Ponieważ aby uzyskać te dane (nazwę i hasło, które zostanie wprowadzone) z żądania (już znajdującego się w serwlecie), użyjemy dokładnie tej nazwy i hasła. Ale o tym później. Sam przycisk do wysyłania danych jest ponownie wykonany w formie przycisku, a nie wejścia, jak to zwykle bywa. Nie wiem na ile ta opcja jest uniwersalna, ale u mnie działa w Chrome :)
Przetwarzanie żądania POST za pomocą serwletu.
Wróćmy do serwletu AddServlet. Wiemy już, że aby nasz serwlet mógł „przechwytywać” żądania GET, nadpisujemy metodę doGet() z klasy HttpServlet. Aby nauczyć nasz serwlet przechwytywania żądań POST, nadpisujemy także metodę doPost(). Otrzymuje podobne obiekty żądań i odpowiedzi od Tomcata, z którym będziemy pracować. Najpierw wyodrębnijmy z żądania nazwę i przekażmy parametry, które wysłał formularz (jeśli w formularzu nazwałeś je inaczej, to takie właśnie nazwy wpisujesz). Następnie na podstawie otrzymanych danych utworzymy nasz obiekt użytkownika. Następnie pobierzemy obiekt modelu i dodamy utworzonego użytkownika do modelu. @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); }
Przesyłanie danych do widoku.
Przejdźmy teraz do serwletu ListServlet. Zaimplementowaliśmy już metodę doGet(), która po prostu przekazuje kontrolę do widoku list.jsp. Jeśli jeszcze tego nie masz, zrób to analogicznie, tą samą metodą z serwletu AddServlet. Teraz byłoby miło pobrać listę nazw użytkowników z modelu i przekazać je do widoku, który je tam odbierze i ładnie wyświetli. W tym celu ponownie skorzystamy z obiektu żądania, który otrzymaliśmy od Tomcata. Do tego obiektu możemy dodać atrybut, nadając mu nazwę i tak naprawdę sam obiekt, który chcemy przenieść do widoku. Z uwagi na to, że przenosząc proces wykonania z serwletu do widoku, przekazujemy tam te same obiekty żądań i odpowiedzi, które sam serwlet otrzymał, to dodając do obiektu żądania naszą listę nazw, możemy wówczas z tego żądania obiekt w widoku utwórz naszą listę nazw użytkowników i pobierz. Skończyliśmy z klasą ListServlet, więc oto kod całej klasy. 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 names = model.list(); req.setAttribute("userNames", names); RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp"); requestDispatcher.forward(req, resp); } }
Wykonywanie kodu Java w plikach jsp.
Przejdźmy teraz do pliku list.jsp. Ten plik zostanie wykonany tylko wtedy, gdy ListServlet przejdzie tutaj proces wykonywania. Dodatkowo w tym serwlecie przygotowaliśmy już listę nazw użytkowników z modelu i przekazaliśmy ją tutaj w obiekcie żądania. Mając listę nazw, możemy uruchomić przez nią pętlę for i wydrukować każdą nazwę. Jak już mówiłem, pliki jsp mogą wykonywać kod Java (w zasadzie to właśnie odróżnia je od statycznych stron HTML). Aby wykonać jakiś kod wystarczy umieścić konstrukcję w potrzebnym nam miejscu. <% // java kod %> Wewnątrz takiej konstrukcji uzyskujemy dostęp do kilku zmiennych: request - nasz obiekt żądania, który przekazaliśmy z serwletu, gdzie został po prostu wywołany req odpowiedź - obiekt odpowiedzi, w serwlecie nazwano resp out - obiekt typu JspWriter (odziedziczony od zwykłego Writera), za pomocą którego możemy „wpisać” coś bezpośrednio do samej strony HTML. Out.println("Witaj, świecie!") jest bardzo podobne do System.out.println("Witaj, świecie!"), ale nie myl ich! out.println() "zapisuje" na stronę HTML, a System.out.println - na wyjście systemowe. Jeśli wywołasz metodę System.out.println() wewnątrz sekcji z kodem jsp, wyniki zobaczysz w konsoli Tomcat, a nie na stronie, jak chcesz :) Możesz poszukać innych dostępnych obiektów wewnątrz jsp Tutaj . Za pomocą obiektu request możemy uzyskać listę nazw przekazanych z serwletu (do obiektu dołączyliśmy odpowiedni atrybut), a za pomocą obiektu out możemy wyświetlić te nazwy. Zróbmy to na razie po prostu w formie listy HTML: Jeśli chcemy wyświetlić listę tylko wtedy, gdy istnieją użytkownicy, a w inny sposób wyświetlić ostrzeżenie, że nie ma jeszcze żadnych użytkowników, możemy trochę przepisać tę sekcję: Teraz, gdy wiedzieć, jak przesyłać dane z serwletów do widoków - możemy nieco ulepszyć nasz AddServlet, aby wyświetlało się powiadomienie o pomyślnym dodaniu użytkownika. W tym celu w metodzie doPost() po dodaniu nowego użytkownika do modelu możemy dodać nazwę tego użytkownika do atrybutów obiektu req i przekazać kontrolę z powrotem do widoku add.jsp. A w nim już utwórz sekcję z kodem Java, gdzie możesz sprawdzić, czy taki atrybut znajduje się w żądaniu, a jeśli tak, to wyświetlić komunikat, że użytkownik został pomyślnie dodany. Po tych zmianach pełny kod serwletu AddServlet będzie wyglądał mniej więcej tak: Tutaj na końcu metody doPost() ustawiamy atrybut z nazwą użytkownika dodanego do modelu, a następnie wywołujemy funkcję doGet( ), do której przekazujemy bieżące żądanie i odpowiedź. Natomiast metoda doGet() przekazuje już kontrolę do widoku, gdzie wysyła obiekt żądania z dołączoną jako atrybut nazwą dodanego użytkownika. Pozostaje poprawić sam add.jsp, aby wyświetlał takie powiadomienie, jeśli taki atrybut występuje. Końcowy dodatek.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    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); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    Treść strony składa się z elementu div z nagłówkiem, po którym następuje kontener div na treść sprawdzającą, czy istnieje w nim atrybut z nazwą użytkownika, następnie element div z formularzem dodawania użytkowników, a na końcu stopka z przycisk umożliwiający powrót do strony głównej. Może się wydawać, że jest za dużo elementów div, ale użyjemy ich później, dodając style :) Cóż, ostateczna wersja to list.jsp. Zatem mamy w pełni działającą aplikację internetową, która może przechowywać i dodawać użytkowników jak wyświetlić listę ich nazw. Pozostaje tylko ozdobić... :) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    Dodawanie stylów. Używamy frameworka W3.CSS.
    W tej chwili nasza aplikacja działa, ale jest totalnie szalona :) Musimy dodać tło, kolory tekstu i przycisków, stylizować listy, wyrównać, dodać wcięcia i ogólnie mnóstwo rzeczy. Jeśli piszesz style ręcznie, może to zająć dużo czasu i nerwów. Dlatego sugeruję użycie frameworka CSS W3.CSS . Posiada już gotowe klasy ze stylami, pozostaje tylko umieścić w odpowiednich miejscach klasy CSS, które chcemy w tych miejscach zastosować. Aby dodać je do naszych stron, najpierw musimy załączyć plik ze stylami. Można to zrobić na dwa sposoby: 1. przejdź po naszych stronach iw sekcji nagłówka wstaw bezpośredni link do pliku ze stylami. Opcja ta jest odpowiednia, jeśli masz stałe połączenie z Internetem. Następnie, gdy otworzysz strony na serwerze lokalnym, style zostaną pobrane z Internetu. 2. Jeśli chcesz mieć wszystkie style lokalnie i nie być zależnym od połączenia internetowego, możesz po prostu pobrać plik ze stylami i umieścić go gdzieś w folderze web (na przykład web/styles/w3.css), a następnie przejdź na wszystkie nasze strony (index.html, add.jsp, list.jsp) i wprowadź link do tego pliku ze stylami w sekcji head. Następnie po prostu przejdź przez tagi i oznacz je stylami, które lubisz . Nie będę się nad tym szczegółowo rozwodzić, ale od razu podam gotowe wersje moich trzech plików z ułożonymi klasami stylów. indeks.html add.jsp list.jsp To wszystko :) Jeśli masz jeszcze jakieś pytania, uwagi lub wręcz przeciwnie, coś nie działa - zostaw komentarz. Cóż, załączę kilka zrzutów ekranu pokazujących, co z tego wszystkiego wyszło. I w końcu. Jeśli chcesz poćwiczyć z tym projektem, możesz spróbować: Super app!

    Super app!

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

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

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

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    Strona główna aplikacji Dodaj okno użytkownika lista użytkowników
    • utwórz serwlet i plik jsp, aby usunąć użytkownika i kilka innych, aby zmienić/edytować istniejącego użytkownika. Otrzymasz prawdziwą aplikację internetową CrUD :) na serwletach))
    • zastąp listę (Lista ) do pracy z bazą danych, aby dodani użytkownicy nie zniknęli po restarcie serwera :)
    Powodzenia!
    Komentarze
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION