Serwlety, JavaServer Pages (JSP)

Post on 16-Jul-2022

12 views 0 download

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("bond007@hotmail.com"); 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')}