Download - Serwlety, JavaServer Pages (JSP)
Serwlety, JavaServer Pages (JSP)
Marek Wojciechowski, Maciej Zakrzewicz
Architektura serwletów Java
serwer
HTTP
HTTP serwlet
Java
serwer
aplikacji
Java EE logika
biznesowa
klient HTTP
• Komponent rozszerzający funkcjonalność serwera
• Obsługuje rozkazy (metody) protokołu HTTP
Zastosowania serwletów Java
• Tradycyjne zastosowanie:
– obsługa formularzy HTML
– generacja stron HTML
• Współczesne zastosowania:
– obsługa danych binarnych, upload / download plików
– kontroler / dyspozytor żądań w aplikacjach MVC
– punkt dostępowy do usług Web Services
– uwierzytelnianie / autoryzacja
Struktura serwletu Java
• Klasa dziedzicząca z HttpServlet
• Implementacja (nadpisanie) co najmniej jednej z metod:
– doGet()
– doPost()
– doDelete(), doPut(), …
– init()
– destroy()
Przykładowy serwlet Java
import javax.servlet.http.*; import java.io.*; public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String fname = request.getParameter("fname"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML><BODY>"); out.println("<H2>Hello " + fname + "!</H2>"); out.println("</BODY></HTML>"); }}
Odwzorowanie serwletu na adres URL
• Rozwiązanie współczesne: adnotacja @WebServlet
• Rozwiązanie starsze: odwzorowanie w pliku web.xml
@WebServlet(name="HelloServlet", urlPatterns= {"/HelloServlet"}) public class HelloServlet extends HttpServlet { … }
<web-app …> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>servlets.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/HelloServlet</url-pattern> </servlet-mapping> …
• Uwaga: URL może zawierać znak * (wzorzec adresu)
Plik web.xml
• Standardowy deployment descriptor dla modułu webowego aplikacji Java EE
– poszczególne serwery mają dodatkowo swój specyficzny plik
• Zawiera ustawienia dotyczące m.in. :
– odwzorowania serwletów na adresy URL
• nadpisujące ewentualną adnotację w kodzie
– timeout sesji HTTP
– ustawienia uwierzytelniania
– ustawienia autoryzacji dostępu do adresów URL
– ustawienie filtrów serwletów
– wskazanie strony startowej
Cykl życia serwletu Java
MyServlet1
doGet()
init()
destroy()
serwer aplikacji
Java EE
klient HTTP
2
4 1
3
n
doGet()
destroy()
init()
Wielowątkowość serwletu
• Współcześnie serwlety są wielowątkowe
– Jedna instancja w kontenerze
– Współbieżne żądania są obsługiwanie we współbieżnych wątkach
• Przechowywanie danych (nie tylko do odczytu) w polach instancji serwletu wymaga synchronizacji i jest niezalecane
• Bezpieczne są dane przechowywane w zmiennych lokalnych metod serwletu
• Współdzielenie danych między komponentami aplikacji i sesjami użytkowników realizuje się przez zasięgi (ang. scopes)
Obiekty zasięgu dostępne dla serwletu
• Zasięg całej aplikacji webowej (Web context)
– javax.servlet.ServletContext
• Zasięg sesji HTTP
– javax.servlet.http.HttpSession
• Zasięg żądania HTTP
– javax.servlet.http.HttpServletRequest
• Uwaga: strony JSP dodatkowo mają zasięg strony:
– javax.servlet.jsp.JspContext
Interfejs HttpServletRequest
• Cookie[] getCookies()
• String getHeader(n)
• String getMethod()
• String getRemoteUser()
• HttpSession getSession()
• String getParameter(n)
• String getRemoteAddr()
• Object getAttribute(n)
• void setAttribute(n, o)
żądanie
HTTP
request
Odczyt parametrów żądania HTTP
• request.getParameter()
• request.getParameterNames()
• request.getParameterValues()
float x = Float.parseFloat(request.getParameter("x")); float y = Float.parseFloat(request.getParameter("y")); float result = x * y; response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML><BODY>"); out.println(x + " * " + y + " = " + result); out.println("</BODY></HTML>");
Serwlety Java - metody doXXX()
• Metoda doGet() odpowiada na żądania typu GET
• Metoda doPost() odpowiada na żądania typu POST
• Jednakowy dostęp do parametrów żądania
• Identyczne lub różne implementacje
– często identyczne w tradycyjnych zastosowaniach (obsługa formularzy HTML)
– różne, zgodne ze specyfikacją HTTP (wraz z doPut() i doDelete()), we współczesnych zastosowaniach
public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {...} public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {...}}
Interfejs HttpServletResponse
• void addCookie(c)
• void addHeader(n,v)
• void sendError(v)
• void sendRedirect(url)
• void setHeader(n,v)
• PrintWriter getWriter()
• ServletOutputStream getOutputStream()
• void flushBuffer()
odpowiedź
HTTP
response
Sesje HTTPSession
• Problem: protokół HTTP jest bezstanowy
• Emulacja sesji (identyfikacja klienta, timeout)
• Każda sesja otrzymuje identyfikator
– przekazywany przez cookie / URL rewriting
• Stan sesji przechowywany przez serwer aplikacji
• Stan sesji usuwany po wygaśnięciu czasu ważności
• Uwaga: stan sesji może być replikowany w klastrze serwerów
– obiekty przechowywane w sesji powinny być serializowalne (java.io.Serializable)
class Employee implements Serializable { … }
Architektura HTTPSession
ID CZAS_DOSTĘPU STAN ...
324 20:45
567 20:20
x:
x:
y:
klient HTTP
klient HTTP
serwer aplikacji
ID=324
ID=567
żądanie HTTP serwlet Java
tablica sesji
HTTPSession
Wykorzystywanie HTTPSession
Employee e = new Employee(); e.setFirstName("Marek"); e.setCity("Poznań"); HttpSession mySess = request.getSession(true); mySess.setAttribute("emp1", e);
HttpSession mySess = request.getSession(false); Employee e = (Employee) mySess.getAttribute("emp1"); out.println(e.getFirstName() + " " + e.getCity());
JavaServer Pages (JSP)
• Technologia umożliwiająca łącznie statycznego kodu HTML lub XML z dynamicznym kodem Java
• Rozszerzenie technologii serwletów
• Podstawowe narzędzie tworzenia warstwy prezentacji w architekturze Java EE
– z wyjątkiem aplikacji JSF gdzie wyparte przez Facelets
• Wersje technologii JSP sparowane z wersjami serwletów
– np. JSP 2.3 / Servlet 3.1 w ramach Java EE 7
– od czasu usamodzielnienia się technologii JSF (zastąpienie JSP przez Facelets) zmiany w JSP kosmetyczne
Przykład prostej strony JSP
<%@ page language="java" %> <html> <head> <title>Currency Converter v.0.1</title> </head> <body> <jsp:include page="header.jsp"/> <%! double priceEUR = 10, pricePLN = 0; %> <%! double ratioPLN2EUR = 4.25; %> <% pricePLN = priceEUR * ratioPLN2EUR; %> <p> <%= priceEUR %> EUR = <%= pricePLN %> PLN </body> </html>
dyrektywa
akcja
deklaracja
skryptlet
wyrażenie
statyczna
zawartość
Wywołanie strony JSP z serwletu
• Wywołanie strony JSP z serwletu
– pobranie kontekstu serwletu
– pobranie zarządcy żądań
– przekierowanie przez include() lub forward()
• Przekazanie danych z serwletu do strony JSP
– umieszczenie parametrów w adresie URL
– wykorzystanie obiektu request
Wywołanie strony JSP z serwletu: Przykład
ServletContext ctx = this.getServletContext(); RequestDispatcher dispatcher = ctx.getRequestDispatcher("/simplePage.jsp"); request.setAttribute("name","James Bond"); dispatcher.forward(request,response);
<%@page contentType="text/html"%> <html> <body> <h1>JSP Page</h1> Hello <%= request.getAttribute("name") %>! </body> </html>
simplePage.jsp
simpleServlet.java
Język wyrażeń Expression Language (EL)
• Niewygodna składnia wyrażeń JSP <tag attribute="<%= request.getAttribute("name") %>">
• Język wyrażeń (JSP Expression Language, JSP EL) wprowadzony w JSP 2.0 – uproszczenie kodu: <tag attribute="${name}">
– opcjonalność: <%@ page isELIgnored="true" %>
– dodatkowe obiekty predefiniowane
– zmienne: tablice, mapy, listy, własności
– ewaluacja wyrażeń, warunków logicznych
• Obecnie Unified EL: wspólny język wyrażeń dla JSP i JSF
– w JSF więcej możliwości i składnia #{…}
JSP EL: Obiekty predefiniowane
• Dodatkowe obiekty predefiniowane: – pageContext: pełen kontekst strony JSP
– param: wartość parametru
– paramValues: tablica wartości parametrów
– header: wartość nagłówka HTTP
– headerValues: tablica wartości nagłówków HTTP
– cookie: wartość ciasteczka
– initParam: wartość parametru inicjalizacyjnego
– pageScope, requestScope, sessionScope, applicationScope: obiekty zasięgów
JSP EL: Literały i operatory
• Literały – logiczne: true i false
– liczby całkowite i zmiennoprzecinkowe
– łańcuchy znaków
• Operatory – arytmetyczne: + - * / % mod div
– logiczne: and or not && || !
– porównania: == != => > <= < lt gt le ge eq ne
– empty, warunkowy A ? B : C
JSP EL: Przykład
ServletContext ctx = this.getServletContext(); RequestDispatcher dispatcher = ctx.getRequestDispatcher("/simplePage.jsp?code=007"); request.setAttribute("name","James Bond"); dispatcher.forward(request,response);
<%@page contentType="text/html"%> <html> <body> Hello ${name}! Your browser is ${header["user-agent"]}. Your secret code is ${param.code}. </body> </html>
simplePage.jsp
simpleServlet.java
package view; public class UserBean implements java.io.Serializable { private String username; private String email; public UserBean() {} public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
Komponenty JavaBean w JSP (1/2)
UserBean.java
<%@page contentType="text/html"%> <html> <body> My name is ${user.email}. </body> </html>
Komponenty JavaBean w JSP (2/2)
ServletContext ctx = this.getServletContext(); RequestDispatcher dispatcher = ctx.getRequestDispatcher("/SimpleBeanPage.jsp"); UserBean user = new UserBean(); user.setUsername("James Bond"); user.setEmail("[email protected]"); request.setAttribute("user", user); dispatcher.forward(request, response);
simpleBeanServlet.java
simpleBeanPage.jsp
Standardowa biblioteka JSTL
• JSP umożliwia programistom definiowanie własnych znaczników
• JSTL (ang. JavaServer Pages Standard Tag Library)
– specyfikacja rozwijana przez Sun: JSR-52
– aktualna wersja: 1.2 (maj 2006)
– podstawowa implementacja: Jakarta Taglibs
• Kategorie znaczników JSTL
– ogólnego przeznaczenia, warunkowe i iteracyjne
– formatowanie tekstu i internacjonalizacja
– manipulacja dokumentami XML
– dostęp do baz danych
– funkcje
JSTL: Znaczniki podstawowe
• <@% taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
• Znaczniki ogólnego przeznaczenia – <c:out> <c:set> <c:remove> <c:catch>
• Znaczniki do iteracji – <c:forEach> <c:forTokens>
• Znaczniki wyboru warunkowego – <c:if> <c:choose> <c:when> <c:otherwise>
• Znaczniki do manipulacji adresami URL – <c:url> <c:param> <c:redirect>
JSTL: Znaczniki formatujące
• <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
• Znaczniki obsługujące pakiety językowe – <fmt:setBundle> <fmt:setLocale>
• Znaczniki obsługujące strefę czasową – <fmt:setTimeZone>
• Znaczniki formatujące daty i liczby – <fmt:formatNumber> <fmt:formatDate>
• Inne znaczniki – <fmt:message> <fmt:param>
JSTL: Funkcje
• <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
• Znaczniki reprezentujące zestaw przydatnych funkcji, głównie do przetwarzania łańcuchów znaków – <fn:contains>, <fn:startsWith>, <fn:endsWith>
– <fn:split>, <fn:join>
– <fn:substring>, <fn:indexOf>, <fn:replace>
– <fn:toLowerCase>, <fn:toUpperCase>
– <fn:length>, <fn:trim>
– <fn:escapeXml>
– ...
• Używane w wyrażeniach EL, a nie jako samodzielne znaczniki, np. ${fn:toUpperCase('jsp')}