Servlety – aplikacje sieciowe
Serwlety to technologia, która umożliwia tworzenie dynamicznych stron internetowych. Chociaż serwlety nie mają ściśle określonego typu obsługiwanych żądań, to naszym głównym powodem zainteresowania będzie ich najczęstsze zastosowanie – czyli aplikacje sieciowe korzystające z protokołu HTTP.
Jak działają servlety
Servlety działają w architekturze klient-serwer. W pewnym uproszczeniu ten model pozwala na podział ról na:
- klienta – wysyła żądanie odpowiedzi od serwera,
- serwer – dostawcę usługi, który przesyła odpowiedź do stacji klienta.
Servlet możemy uruchomić np. na serwerze Tomcat. Klientem natomiast może być przeglądarka, która wyświetli stronę html lub zwykła aplikacja desktopowa, która powinna zapewniać możliwość użycia protokołu HTTP w celu nawiązania połączenia w servletem.

Aplikacje sieciowe
Aplikacje sieciowe służą do tworzenia dynamicznych treści. Możemy je podzielić na dwa typy.
- Prezentacyjne – zorientowane na tworzenie dynamicznych stron internetowych oraz ich prezentację użytkownikowi. Przy ich tworzeniu przydatne są technologie Java Server Pages, Java Server Faces oraz Facelets.
- Usługowe – zorientowane na udostępnianiu usług. Do ich implementacji przydatne są serwlety.
Klasa HttpServlet
Tworząc własne klasy serwletów możemy wykorzystać mechanizm dziedziczenia, dzięki czemu możemy skupić się na metodach protokołu HTTP takich jak get, post, delete oraz put. Serwer wywołując metodę service() pozwala wykorzystywać poniższe metody.
doGet()
– nadpisanie tej metody pozwala obsługiwać żądanie oraz dane przesłane metodą get protokołu HTTP oraz wysłać odpowiedź.doPost()
– Podobnie jak wyżej z tą różnicą, że dotyczy to zapytania post.doPut()
– pozwala na przechwycenie metody put.doDelete()
– przechwycenie delete.
Cykl życia servletu
- Wczytanie klasy serwletu.
- Utworzenie instacji klasy serwletu.
- Inicjalizacja metodą init() serwletu.
- Kontener serwletów wykonuje metodę
service()
- usunięcie serwletu metodą
destroy()
.
Tworzenie własnego servletu
Aby utworzyć serwlet będziemy potrzebowali wersję Eclipse EE oraz zainstalowany serwer np. Tomcat, Jetty. Instalacja przebiega tak samo jak w przypadku standardowej wersji. Podobnie pierwszym krokiem będzie założenie nowego projektu. Klikamy.
File → New → Dynamic Web Project
Powinniśmy zobaczyć następujące okienko.

Uzupełniamy w nim nazwę projektu oraz możemy wybrać od razu wcześniej skonfigurowane środowisko np. Apache Tomcat 9. Możemy od razu kliknąć Finish.
Po przejściu przyciskiem next jest opcja wygenerowania pliku XML, który przy aktualnej wersji Javy nie jest konieczny. Wszystkie informacje, które kiedyś były w nim zawarte są aktualnie umieszczone w specjalnych znacznikach.
Kolejnym krokiem jest utworzenie serwletu. W tym celu klikamy.
Java Resources → src → new servlet

Następnie w powyższym okienku uzupełniamy nazwę oraz pakiet. Zwróćmy uwagę, że klasą nadrzędną automatycznie jest wpisana klasa HttpServlet
. Przechodzimy dalej do ostatniego okienka.

Wybieramy tak jak na obrazku jedynie utworzenie metody doGet()
ponieważ tylko ją aktualnie chcemy obsłużyć. Klikamy Finish i pokaże nam się automatycznie wygenerowany serwlet. Możemy spróbować go od razu uruchomić przyciskiem Run Servlet.
Po kliknięciu next wybieramy klasę naszego serwletu i dodajemy go na prawą stronę. Następnie Finish.

Uruchomimy w ten sposób serwlet, a Eclipse w swojej wbudowanej przeglądarce pokaże nam odpowiedź od serwera Tomcat. Czemu jednak od razu pokazał nam się błąd?

Otóż otworzyliśmy główny folder na naszym serwerze, który jest pusty. Aby wykonać metodę doGet()
musimy dopisać do adresu część zawartą w adnotacji. Aby jednak wyświetlić jakąkolwiek treść w naszym głównym adresie wystarczy utworzyć dokument index.html w folderze WebContent. Po uaktualnieniu się danych na serwerze powinniśmy otrzymać treść naszego dokumentu.

Poniżej wyświetlamy wynik uruchomienia metody doGet()
.

Wygenerowany automatycznie kod serwletu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package pl.programistajava; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class Test */ @WebServlet("/Test") public class Test extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public Test() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //String par = request.getParameter("parametr1"); response.getWriter().append("Odpowiedz"); } } |
Powyżej znajduje się kod wygenerowany automatycznie. Zwróćmy uwagę na kilka rzeczy.
@WebServlet(„/Test”)
To jest fragment wskazujący pod jakim adresem będzie znajdował się serwlet. Poniżej pokazujemy pełny adres.
http://localhost:8080/MojServlet/Test
- localhost – jest nazwą hosta możliwą do ustawienia w konfiguracji serwera.
- 8080 – numer portu, na którym serwer nasłuchuje żądań http.
- MojServlet – adres serwletu.
- Test – podany przez nas adnotacja wskazująca pod jakim adresem znajduje się wykonywany przez nas kod.
Zwróćmy również uwagę na argumenty metody doGet()
. Pierwszy jest obiektem klasy HttpServletRequest
i pozwala na odbieranie parametrów przesłanych metodą post lub get. Drugi natomiast jest klasy HttpServletResponse
i to właśnie on pozwala serwletowi na odpowiedź.
Przekazywanie parametrów get
W celu pokazania przekazywania parametrów przyda nam się dodatkowy dokument z formularzem, dlatego zmodyfikujmy nasz index.html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html> <HEAD> </HEAD> <body> <H1>Przekazywanie parametrów</H1> <form action="/MojServlet/Get" method="get"> Podaj swoje imię: <input type="text" name="imie"></br> <input TYPE="submit" VALUE="Wyślij"> </form> </body> </html> |
A poniżej pokazujemy klasę serwletu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package pl.programistajava; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/Get") public class Test extends HttpServlet { private static final long serialVersionUID = 1L; public Test() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String par = request.getParameter("imie"); response.setContentType("text/html; charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.getWriter().append("<!DOCTYPE html>" + "<html>\n" + "<body>\n" + "<h1>" + "Odpowiedź od serwera" + "</h1>\n" + "<p>Witaj " + par + ", Właśnie przesłałeś swój parametr metodą get!</p>\n" + "</body>\n" + "</html>" ); } } |
Uruchomienie serwletu wygląda następująco.

Oraz efekt wykonania kodu po stronie serwera i odpowiedź.

Zwróćmy uwagę na to, że odpowiedź serwera czyli kod html jest zawarty w kodzie Javy, co nie jest wygodne, gdy dokument jest skomplikowany.
Przekazywanie parametrów post
Metoda post jest nieco wygodniejsza przy przesyłaniu większej liczby parametrów gdyż nie jest widoczna w adresie URL. Minusem tego rozwiązania jest jednak brak możliwości wysłania bezpośrednio zapytania bez wypełnienia formularza podstawiając samemu parametry w linku.
Naszym zadaniem będzie obliczenie wyznacznika macierzy 3×3. Zadanie jest proste. Potrzebujemy tylko pola tekstowego, które przyjmie dane od użytkownika. Zakładamy, że 3 pierwsze liczby będą pierwszym rzędem, trzy następne drugim itd. Załóżmy również, że będziemy obliczać wyłącznie wyznaczniki macierzy składające się z liczb całkowitych dodatnich. Tym razem będziemy potrzebowali metody doPost()
. W przypadku jej braku dostaniemy po prostu odpowiedź, że żądanie nie może zostać obsłużone.
Poniżej znajduje się zawartość pliku index.html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!DOCTYPE html> <html> <HEAD> </HEAD> <style> body { background: #f2f2f2; } textarea { resize: none; width: 200px; height: 150px; font-size: 1.5rem; } p { font-size: 1.2rem; } </style> <body> <H1>Przekazywanie parametrów metodą post</H1> <form action="/MojServlet/Det" method="post"> <p>Wypisz macierz 3x3 do obliczenia jej wyznacznika:</p></br> <textarea name="macierz" rows="3" cols="10"></textarea> <input TYPE="submit" VALUE="Oblicz"> </form> </body> </html> |
Poniżej kod naszego serwletu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package pl.programistajava; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Scanner; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/Post") public class Macierz extends HttpServlet { private static final long serialVersionUID = 1L; public Macierz() { super(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int[][] matrix = new int[3][3]; String req = request.getParameter("macierz").trim(); Scanner sc = new Scanner(req); sc.useDelimiter("\\D+"); while(sc.hasNextInt()){ for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { matrix[i][j] = sc.nextInt(); } } } sc.close(); response.setContentType("text/html; charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.getWriter().append("<!DOCTYPE html>" + "<html>\n" + "<body>\n" + "<h1>" + "Odpowiedź od serwera" + "</h1>\n" + "<p>Wyznacznikiem macierzy " + Arrays.deepToString(matrix) + " jest " + det(matrix)+ "</p>\n" + "</body>\n" + "</html>" ); } private int det(int[][] mat) { int det = mat[0][0]*mat[1][1]*mat[2][2] + mat[0][1]*mat[1][2]*mat[2][0] + mat[0][2]*mat[1][0]*mat[2][1] - mat[0][2]*mat[1][1]*mat[2][0] - mat[0][0]*mat[1][2]*mat[2][1] - mat[0][1]*mat[1][0]*mat[2][2]; return det; } } |
Przekazywanie parametrów wygląda podobnie jak w przypadku metody doGet()
. Różnicą jest natomiast to, że tym razem nie widać ich w linku. Poniżej znajduje się przykładowe działanie serwletu.

Oraz odpowiedź od serwera
