Witam wszystkich! Zapoznasz się z serwletami jako podstawową koncepcją tworzenia stron internetowych i będziesz w stanie napisać prostą aplikację, która ich używa. Twoja pierwsza aplikacja wykorzystująca serwlety Java - 1 Aby uniknąć niepotrzebnych działań, nie będziemy zaczynać od zera. Będziemy kontynuować pracę nad naszą aplikacją z mojego poprzedniego artykułu o Hibernate . Ponieważ jednak dopiero zaczynamy poznawać serwlety, usunąłem z aplikacji wszystko, co było związane z klasą Auto i zostawiłem tylko klasę User i działania z nią związane. Projekt będzie miał następującą strukturę: Twoja pierwsza aplikacja wykorzystująca serwlety Java - 2A więc serwlety! Wikipedia stwierdza: „A serwlet Java to składnik oprogramowania Java, który rozszerza możliwości serwera. Chociaż serwlety mogą odpowiadać na wiele typów żądań, najczęściej implementują kontenery internetowe do hostowania aplikacji internetowych na serwerach internetowych, a tym samym kwalifikują się jako serwer- internetowy interfejs API serwletu”. To jest dokładnie prawda. Tutaj po raz pierwszy spotykamy się z pojęciem „architektury aplikacji klient-serwer”. Jest to dość proste w swej istocie. Klient uzyskuje dostęp do serwera, wysyłając żądanie HTTP. Serwer generuje potrzebne dane (np. pobiera je z bazy danych) i zwraca klientowi. Najprostszym przykładem jest kliknięcie przycisku „Przyjaciele” w określonej sieci społecznościowej, wysyłając w ten sposób żądanie do serwera. Serwer aktualizuje listę Twoich znajomych w bazie danych i zwraca ją Tobie (klientowi). Lista żądań HTTP jest dość obszerna, więc jeśli nigdy wcześniej się z nimi nie spotkałeś, najlepiej byłoby, gdybyś o nich przeczytał gdzie indziej, np.tutaj . Naszym celem jest: Stworzenie aplikacji CRUD z wykorzystaniem serwletów. Aplikacja musi mieć możliwość tworzenia, odczytywania, aktualizowania i usuwania użytkowników z bazy danych za pomocą serwletu przetwarzającego żądania HTTP. Nasza aplikacja z artykułu Hibernate już to potrafiła, ale była sterowana bezpośrednio z kodu Javy, a dokładniej z metody main(). Tym razem to klient będzie wysyłał żądania, czyli Ty :) Pierwszą rzeczą, którą musimy zrobić, to dodać nowe zależności do naszego pliku pom.xml.

 <xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>com.itis4</groupId>
     <artifactId>UsersDaoProject</artifactId>
     <version>1.0-SNAPSHOT</version>
 
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-war-plugin</artifactId>
                 <version>2.6</version>
             </plugin>
         </plugins>
     </build>
 
     <dependencies>
         <!-- PostgreSQL  -->
         <dependency>
             <groupId>org.postgresql</groupId>
             <artifactId>postgresql</artifactId>
             <version>9.4.1212.jre7</version>
         </dependency>
 
         <!-- Hibernate 5.2.6 Final -->
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
             <version>5.2.6.Final</version>
         </dependency>
 
         <dependency>
             <groupId>jstl</groupId>
             <artifactId>jstl</artifactId>
             <version>1.2</version>
         </dependency>
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
             <version>3.1.0</version>
         </dependency>
 
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
             <version>4.3.4.RELEASE</version>
         </dependency>
 
     </dependencies>
 
 </project>
 
Dodaliśmy 3 zależności:
  1. Sama biblioteka javax.servlet-api
  2. Biblioteka znaczników JSTL. Konieczne będzie utworzenie strony klienckiej, czyli stron JSP
  3. Spring-WebMVC. Będziemy potrzebować jednej klasy wiosennej, o której porozmawiamy nieco później.
Zarządzanie serwletami jest obsługiwane przez kontener serwletów. W naszym przypadku użyjemy Apache Tomcat. Jest dość popularny — prawdopodobnie już o nim słyszałeś :) Cykl życia serwletu składa się z następujących kroków:
  1. Jeśli w kontenerze nie ma serwletu:
    • Klasa serwletu jest ładowana przez kontener.
    • Kontener tworzy instancję klasy serwletu.
    • Kontener wywołuje metodę init(). Ta metoda inicjuje serwlet i jest wywoływana jako pierwsza, zanim serwlet będzie mógł obsłużyć żądania. W ciągu całego cyklu życia metoda init() jest wywoływana tylko raz.
  2. Obsługa żądania klienta. Każde żądanie jest przetwarzane w osobnym wątku. Kontener wywołuje metodę service() dla każdego żądania. Ta metoda określa typ przychodzącego żądania i wysyła je do odpowiedniej metody w celu przetworzenia. Twórca serwletu musi zapewnić implementacje tych metod. Jeśli nadejdzie żądanie procedury obsługi, która nie jest zaimplementowana, wywoływana jest metoda klasy nadrzędnej, co zazwyczaj kończy się zwróceniem błędu do osoby żądającej.

  3. Jeśli kontener musi usunąć serwlet, wywołuje metodę destroy(), która wyłącza działanie serwletu. Podobnie jak metoda init(), ta metoda jest również wywoływana raz podczas całego cyklu serwletu.
Nasz serwlet wygląda dość prosto:

 package servlets;
 
 import models.User;
 import services.UserService;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletConfig;
 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 UserSimpleServlet extends HttpServlet {
 
     private UserService service = new UserService();
 
     public void init(ServletConfig servletConfig) {
         try {
             super.init(servletConfig);
         } catch (ServletException e) {
             e.printStackTrace();
         }
     }
 
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         List<User> users = service.findAllUsers();
         req.setAttribute("users", users);
         RequestDispatcher dispatcher = req.getRequestDispatcher("/showUsers.jsp");
         dispatcher.forward(req, resp);
 
     }
 
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
 
         String name = req.getParameter("name");
         int age = Integer.parseInt(req.getParameter("age"));
         User user = new User(name, age);
         service.saveUser(user);
         resp.sendRedirect("/users");
 
     }
 
     @Override
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         int id = Integer.parseInt(req.getParameter("id"));
         User user = service.findUser(id);
         user.setName(req.getParameter("name"));
         user.setAge(Integer.parseInt(req.getParameter("age")));
         service.updateUser(user);
         resp.sendRedirect("/users");
     }
 
     @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
         int id = Integer.parseInt(req.getParameter("id"));
         service.deleteUser(service.findUser(id));
         resp.sendRedirect("/users");
     }
 }
 
Jak widać zawiera metodę init() opisaną powyżej oraz implementuje 4 metody, które pokrywają się z czterema żądaniami HTTP: doPost(), doGet(), doPut() i doDelete(). Pozwalają nam tworzyć, odczytywać, aktualizować i usuwać użytkowników. Metody przyjmują jako dane wejściowe wystąpienia klas javax.servlet.http.HttpServletRequest i javax.servlet.http.HttpServletResponse, tj. żądania wysyłane do serwera i odpowiedzi otrzymywane przez klienta. Wewnętrznie metody wywołują odpowiednie metody klasy UserService, a odpowiedź dla klienta jest generowana i przekierowywana na adres URL /users. Na przykład w metodzie doGet() otrzymujemy listę wszystkich użytkowników. Następnie tworzymy obiekt RequestDispatcher, który pozwala dołączyć obiekty do żądania HTTP i przekierować je do określonego zasobu (na przykład na stronę JSP klienta). W metodzie doPut() (która aktualizuje dane użytkownika) przetwarzamy żądanie HTTP, wyodrębniamy parametry id, name i age, znajdujemy użytkownika o podanym id, przypisujemy mu imię i wiek podane w żądaniu i zwracamy na stronę /users. Ale aby wszystkie te metody działały poprawnie, musimy skonfigurować serwlet. W tym celu wykorzystujemy plik web.xml znajdujący się w folderze WEB-INF.

 <?xml version="1.0" encoding="UTF-8"?>
 <web-app version="3.1"
          xmlns="http://xmlns.jcp.org/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
 
     <welcome-file-list>
         <welcome-file>index.jsp</welcome-file>
     </welcome-file-list>
 
     <servlet>
         <servlet-name>UserSimpleServlet</servlet-name>
         <servlet-class>servlets.UserSimpleServlet</servlet-class>
     </servlet>
 
     <servlet-mapping>
         <servlet-name>UserSimpleServlet</servlet-name>
         <url-pattern>/</url-pattern>
     </servlet-mapping>
 
     <filter>
         <filter-name>hiddenHttpMethodFilter</filter-name>
         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
     </filter>
 
     <filter-mapping>
         <filter-name>hiddenHttpMethodFilter</filter-name>
         <servlet-name>UserSimpleServlet</servlet-name>
     </filter-mapping>
 
 </web-app>
 
Wszystkie tagi w tym pliku są dość intuicyjne, ale przejrzyjmy je w kolejności. <lista-plików-powitalnych> — wskazywana jest strona początkowa JSP, która zostanie otwarta jako pierwsza po uruchomieniu aplikacji. W naszym przypadku jest to plik index.jsp. <servlet> - Rejestracja naszej klasy UserSimpleServlet jako serwletu. <servlet-mapping> - bardzo ważny znacznik. Definiuje adresy URL, które będą przetwarzane przez serwlet. W naszym przypadku są to wszystkie adresy URL, więc po prostu wskazujemy „/”. Ale gdybyśmy mieli aplikację obejmującą użytkowników i ich samochody (samochody), moglibyśmy stworzyć drugi serwlet (SimpleAutoServlet). Wtedy mapowaniem serwletu użytkownika byłoby „/users” (tj. żądania dotyczące użytkowników), a mapowaniem serwletu automatycznego byłoby „/autos”. I wreszcie <filtr>. Wewnętrznie definiuje instancję org. Klasa springframework.web.filter.HiddenHttpMethodFilter. Ten artykuł nie dotyczy wiosny, więc nie będę jej szczegółowo opisywał. Powiem tylko, że jest przykręcony do naszej aplikacji tylko jako dodatkowa funkcja. Chodzi o to, że będziemy używać stron JSP do tworzenia strony klienta. Nasze dane zostaną wyświetlone na stronie jako tabela z listą użytkowników. Wewnątrz stron JSP będą używane znaczniki HTML <form/>. Jednak tylko żądania HTTP GET i POST mogą być używane do wysyłania danych z formularza <form/>. Innymi słowy, dla wszystkich trzech operacji — aktualizowania, usuwania i tworzenia użytkownika — musielibyśmy używać tylko żądań POST. Korzystanie z żądań PUT i DELETE nie byłoby dla nas opcją. W zasadzie jest to całkiem normalne i łatwe do zaimplementowania, ale klasa HiddenHttpMethodFilter pozwala nam z nich korzystać. W ten sposób, czytelnik wyraźniej zobaczy różnicę między operacjami w aplikacji. Na koniec przejdźmy do strony klienta. Jest reprezentowany przez pięć stron JSP. indeks.jsp.

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Hello!</title>
 </head>
 <body>
 If you want to start working with the user database,<br>
 click the button below:
 
 <form action = "users" method="get">
     <input type="submit" value="Start working with database">
 </form>
 </body>
 </html>
 
addUser.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Add new user</title>
 </head>
 <body>
 <form action = "/users" method="post">
     <input required type="text" name="name" placeholder="Name">
     <input required type="text" name="age" placeholder="Age">
     <input type="submit" value="Save">
 </form>
 </body>
 </html>
 
 
usuńUżytkownik.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Delete user</title>
 </head>
 <body>
 
 Are you sure you want to delete the user ${param.id}?
 
 &lform action="/users/${param.id}" method="post">
     <input type="hidden" name="id" value="${param.id}">
     <input type="hidden" name="_method" value="delete">
     <input type="submit" value="Delete">
 </form>
 
 </body>
 </html>
 
 
showUsers.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <html>
 <head>
     <title>User list</title>
 </head>
 <body>
 <table border="2">
     <tr>
         <td>ID</td>
         <td>Name</td>
         <td>Age</td>
         <td>Actions</td>
     </tr>
     <c:forEach items="${users}" var = "user">
         <tr>
             <td>${user.getId()}</td>
             <td>${user.getName()}</td>
             <td>${user.getAge()}</td>
             <td>
                 <form action = "updateUser.jsp" method="post">
                     <input type="hidden" name="id" value="${user.getId()}">
                     <input type="hidden" name="name" value="${user.getName()}">
                     <input type="hidden" name="age" value="${user.getAge()}">
                     <input type="submit" value="Modify" style="float:left">
                 </form>
                 <form action="deleteUser.jsp" method="post">
                     <input type="hidden" name="id" value="${user.getId()}">
                     <input type="submit" value="Delete" style="float:left">
                 </form></td>
         </tr>
     </c:forEach>
 </table>
 
 <form action = "addUser.jsp">
     <input type="submit" value="Add new user">
 </form>
 </body>
 </html>
updateUser.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Modify user data</title>
 </head>
 <body>
 
 Edit user
 
 <form action="/users/${param.id}" method="post">
     <input type="hidden" name = "id" value="${param.id}">
     <input type="text" name="name" value="${param.name}" placeholder=${param.name}>
     <input type="text" name="age" value="${param.age}" placeholder=${param.age}>
     <input type="hidden" name="_method" value="put">
     <input type="submit" value="Update">
 </form>
 
 </body>
 </html>
 
Strona JSP (JavaServer Page) zawiera dwa rodzaje tekstu: statyczne dane źródłowe, które można sformatować jako tekst (HTML, SVG, WML lub XML) oraz elementy JSP używane do konstruowania zawartości dynamicznej. Aby pomóc Ci zrozumieć, czym jest strona JSP, skopiowałem fragment bardzo dobrego artykułu. „Zasadniczo przy pierwszym żądaniu strony JSP zamienia się ona w serwlet i działa jak serwlet. Jest to bardzo ważne, aby zrozumieć. Strona JSP NIE JEST jak strona HTML — początkujący programista musi jasno zrozumieć, że jest to kolejny serwlet — po prostu nie trzeba pisać, aby zaprogramować sposób wyświetlania. Można to po prostu narysować. I dodać dane tam, gdzie to konieczne. Ale ponieważ strona JSP przypomina HTML, projektantowi będzie to oczywiście łatwiejsze. I jeszcze raz MOCNIE PODKREŚLAJ początkującym,strona JSP to SERWLET. Jest generowany, łącznie z dodaniem wszystkich danych, na serwerze. W tym miejscu wprowadzane są wszystkie dane. A w przeglądarce użytkownik otrzymuje gotową stronę HTML, która nie ma śladów Javy”. Możesz być pewien, że strona JSP to tak naprawdę serwlet, ponieważ każda strona ma metodę, którą należy wykonać. Na przykład index .jsp wskazuje, że po kliknięciu przycisku „Rozpocznij pracę z bazą danych” zostanie wykonana metoda get (method = „get”). Strona addUser.jsp, która odpowiada za tworzenie nowych użytkowników, wykonuje metodę post (method = „post”) po kliknięciu przycisku zapisywania. Reszta strony JSP składa się ze zwykłych, statycznych znaczników HTML, więc nie będziemy się nad tym rozwodzić. To temat na inny artykuł, a jest tego mnóstwo temat w Internecie. Więc my stworzyliśmy naszą aplikację! Teraz musimy przetestować to w działaniu! Aby to zrobić, potrzebujemy wspomnianego powyżej kontenera serwletów Apache Tomcat. Możesz pobrać kontenerz oficjalnej strony (używam wersji 8). Następnie musimy utworzyć konfigurację w IDEA, aby uruchomić naszą aplikację przez Tomcat. Aby to zrobić, otwórz kartę „Edytuj konfiguracje”, Twoja pierwsza aplikacja wykorzystująca serwlety Java - 3utwórz nową konfigurację Twoja pierwsza aplikacja wykorzystująca serwlety Java - 4i wybierz opcję „Lokalny serwer Tomcat”. Na zakładce „Serwer aplikacji” określ ścieżkę do folderu Tomcat Twoja pierwsza aplikacja wykorzystująca serwlety Java - 5. Następnie przejdź do zakładki „Wdrożenie”. Twoja pierwsza aplikacja wykorzystująca serwlety Java - 6Tutaj konfigurujemy wdrożenie naszej aplikacji na lokalnym serwerze. Naciśnij „+”, wybierz „Artifact” -> YourProjectName:war (zbudujemy aplikację do pliku wojny). Twoja pierwsza aplikacja wykorzystująca serwlety Java - 7I to podsumowuje! Na stronie „Serwer” możesz zobaczyć, że nasza aplikacja będzie działać pod adresem http://localhost:8080/. Zapisz konfigurację i nadaj jej nazwę (nazywam moją konfigurację „Tommy”). Następnie w zakładce Maven w IDEA (po prawej stronie) użyjemy wtyczki war do zbudowania naszego projektu do pliku wojny (Plugins -> war -> war: war). Twoja pierwsza aplikacja wykorzystująca serwlety Java - 8Po zakończeniu kompilacji uruchom aplikację i poczekaj. Powodzenie! Uruchomiono stronę startową. Teraz klikamy przycisk „Rozpocznij pracę z bazą danych”. Nasz plik index.jsp wygeneruje żądanie GET, które zostanie przetworzone przez serwer. Serwer wygeneruje odpowiedź i zwróci ją nam w postaci listy wszystkich istniejących użytkowników (zakładając oczywiście, że w bazie są użytkownicy). I oto są! Że masz to! Napisałeś swoją pierwszą aplikację przy użyciu serwletów Java. Twoja pierwsza aplikacja wykorzystująca serwlety Java - 9To nie było takie złe, prawda? :) W ramach pracy domowej możesz przywrócić funkcjonalność samochodu z poprzedniego artykułu. Innymi słowy, utwórz oddzielny serwlet i strony JSP dla samochodów i naucz aplikację, jak wyświetlać listę samochodów użytkownika, dodawać nowe samochody do użytkownika oraz edytować i usuwać je. PS Servlets i JavaServer Pages to dość stare technologie. W Internecie często można znaleźć komentarze w stylu „Po co ten stary rupieć?” Odpowiedź jest dość prosta: głównie ludzie, którzy będą pracować nad prawdziwymi projektami, gdzie całkiem możliwe, że napotkają dużo kodu wykorzystującego te technologie. I nawet nie rozumiejąc, jak to działa, fajnie jest pociąć „stare śmieci” na coś nowego :) Więcej informacji na temat JSP i serwletów można znaleźć w książce „Head First Servlets and JSP . Został napisany przez tych samych autorów, co słynna super książka "Head First Java", którą wielu uzna za gwarancję jakości :) Mam nadzieję, że ten artykuł był pomocny! Dziękuję za uwagę i życzę powodzenia w nauce!