Serwlety, JavaServer Pages (JSP)
Transcript of 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')}