JSP Dodawanie dynamicznej zawartości

Transkrypt

JSP Dodawanie dynamicznej zawartości
JSP
JSP po prostu umieszcza Javę wewnątrz stron HTML . MoŜna wziąć stronę HTML i zmienić
rozszerzenie na ".jsp" zamiast ".html". To jest dobre ćwiczenie na początek.
W tym celu moŜna utworzyć plik hello.html o treści
<HTML>
<BODY>
Hello World!
</BODY>
</HTML>
potem zmienić rozszerzenie z ".html" na ".jsp" i załadować go w przeglądarce.
Będzie ten sam efekt jak przy wyświetlaniu pliku HTML, tylko jego uzyskanie zajmie trochę
więcej czasu :) Ale tylko za pierwszym razem. Przy ponownym załadowaniu, załaduje się
normalnie.
To co się tak naprawdę dzieje to, Ŝe JSP jest przekształcane na plik Javy, kompilowane i
ładowane. Ta kompilacja ma miejsce tylko raz, więc po pierwszym razie ładowanie pliku nie
trwa juz dłuŜej. (Lecz jeśli plik ulegnie zmianie, to konieczna będzie jego rekompilacja.)
Oczywiście, nie jest dobrym pomysłem pisanie stron zawierających jedynie HTML z
rozszerzeniem .jsp :)
Dodawanie dynamicznej zawartości
Jak widzieliśmy, kaŜdy plik.html moŜe być zamieniony na plik.jsp przez prostą zmianę
rozszerzenia, co oczywiście nie ma większego zastosowania. To co czyni JSP przydatnym to
zdolność umieszczania w nim Javy.
Umieść następujący tekst w pliku z rozwinięciem .jsp ( np. hello.jsp), wrzuć go do swojego
katalogu JSP i zobacz jak to wygląda w przeglądarce.
<HTML>
<BODY>
Hello! The time is now <%= new java.util.Date() %>
</BODY>
</HTML>
ZauwaŜ, Ŝe za kaŜdym razem kiedy ładujesz stronę w przeglądarce, pojawia się ona z
bieŜącym czasem.
Charakterystyczne sekwencje: <%= i %> zamykają wyraŜenia javowe które są wykonywane w
czasie run-time. Kod tam zawarty jest wykonywany, zamieniany na string i wpisywany w kod
HTML.
Tak oto moŜliwe jest uŜywanie JSP do generowania dynamicznych stron HTML, które
zmieniają się w odpowiedzi na działania uŜytkownika i róŜnią się dla róŜnych uŜytkowników.
Skryptlety
Wiadomo juŜ, Ŝe wyraŜenia javowe na stronach JSP naleŜy umieszczać pomiędzy
sekwencjami <%= i %> .
Ale trudno jest w ten sposób pisać duŜe kawałki kodu.
JSP pozwala na pisanie całych bloków kodu Javy wewnątrz JSP. Robi się to poprzez
umieszczenie tego kodu wewnątrz <% i %> (tak jak wcześniejszych wyraŜeń, ale bez znaczka =
na początku sekwencji.)
Taki blok kodu nazywa się "skryptlet". Jako taki, skryptlet nie generuje Ŝadnego tekstu do
HTML ( chociaŜ moŜe, jak zaraz zobaczymy). Scryptlet zawiera kod Javy, który jest
wykonywany za kaŜdym razem kiedy JSP jest wywoływane.
Oto zmodyfikowana wersja naszego pliku JSP z poprzedniej sekcji z dodanym skryptletem.
<HTML>
<BODY>
<%
// To jest skryptlet. ZauwaŜ, Ŝe zmienna
// "date" zadeklarowana w pierwszym wbudowanym
// wyraŜeniu jest dostępna równieŜ w tym późniejszym.
System.out.println( "Sprawdzam date" );
java.util.Date date = new java.util.Date();
%>
Hello! The time is now <%= date %>
</BODY>
</HTML>
Jeśli uruchomisz powyŜszy przykład, zauwaŜysz wyjście z "System.out.println" na logu
serwera. Jest to bardzo wygodne przy debuggowaniu ( niektóre serwery udostępniają techniki
debugowania JSP w IDE (Integrated Development Environment). Aby sprawdzić czy nasz
serwer oferuje takie udogodnienia naleŜy zajrzeć w jego dokumentację).
Jak juŜ było powiedziane, skryptlet sam w sobie nie generuje HTML. MoŜna to zrobić
uŜywając w nim zmiennej zwanej "out". Ta zmienna nie musi być deklarowana. Jest
predefiniowana dla skryptletów, razem z kilkoma innymi zmiennymi. Następujący przykład
pokazuje jak skryptlet moŜe generować HTML.
<HTML>
<BODY>
<%
// Ten skryptlet deklaruje i inicjalizuje "date"
System.out.println( " Sprawdzam date " );
java.util.Date date = new java.util.Date();
%>
Hello! The time is now
<%
// Ten skryptlet generuje HTML
out.println( String.valueOf( date ));
%>
</BODY>
</HTML>
Tutaj, zamiast uŜywać wyraŜeń javowych, generujemy bezpośrednio HTML poprzez
wywołanie metody println w zmiennej "out".
Zmienna out" jest typu javax.servlet.jsp.JspWriter.
Kolejną, bardzo uŜyteczną predefiniowaną zmienną jest "request".
Jest ona typu javax.servlet.http.HttpServletRequest
"Request" po stronie serwera odnosi się do transakcji pomiędzy przeglądarką i serwerem.
Kiedy ktoś wchodzi na jakiś URL, przeglądarka wysyła Ŝądanie (request) do serwera o ten
URL i pokazuje zwrócone dane. Jako część tego Ŝądania dostępne są róŜne dane, włączając
w to nazwę pliku, który przeglądarka chce dostać od serwera, i (jeśli Ŝądanie pochodzi z
wciśnięcia guzika SUBMIT) informacje, które uŜytkownik wprowadził do formularza.
Zmienna "request" jest uŜywana do uzyskania informacji z Ŝądania wysyłanego przez
przeglądarkę.
Na przykład moŜna poznać nazwę komputera klienta.
Zmodyfikujmy kod jak poniŜej :
<HTML>
<BODY>
<%
System.out.println( "Sprawdam date" );
java.util.Date date = new java.util.Date();
%>
Hello! Data:
<%
out.println( date );
out.println( "<BR>Your machine's address is " );
out.println( request.getRemoteHost());
%>
</BODY>
</HTML>
"Response" jest podobną zmienną. Jest ona uŜywana, Ŝeby modyfikować odpowiedź
wysyłaną do przeglądarki.
Na przykład aby zawiadomić przeglądarkę, Ŝe trzeba połączyć się z innym adresem URL,
wystarczy napisac:
response.sendRedirect(anotherUrl);
Przeglądarka wtedy wysle inne Ŝądanie do "anotherUrl".
Mieszanie skryptletów z HTMLem
Widzieliśmy juŜ jak uŜywać zmiennej "out" do generowania kodu HTML z wnętrza
skryptletu. Dla bardziej skomplikowanego HTMLa uŜywanie cały czas zmiennej "out"
powoduje, Ŝe programowanie JSP traci niektóre swoje zalety. Łatwiej jest mieszać skryptlety
z HTMLem.
Przypuśćmy, Ŝe chcemy wygenerować tabelkę w HTMLu. Jest to bardzo częsta operacja, np.
generowanie tabel z tabel SQLa, czy z linii pliku. śeby utrzymać nasz przykład w miarę
prostym, wygenerujemy tabelkę z numerami od 1 do N. Istotne jest pokazanie techniki,
dlatego prosty przykład wystarczy.
Oto fragment JSP, który to robi:
<TABLE BORDER=2>
<%
for ( int i = 0; i < n; i++ ) {
%>
<TR>
<TD>Number</TD>
<TD><%= i+1 %></TD>
</TR>
<%
}
%>
</TABLE>
Zanim to zadziała trzeba jeszcze ustawić zmienną int "n" i dostaniemy tabelkę z "n" rzędami.
WaŜną rzeczą jest jak znaki %> i <% pojawiają się w środku pętli "for", co pozwala wracać do
HTMLa a potem z powrotem do skrypletu.
ZałoŜenia są proste -- jak widać, moŜna wyskoczyć ze skryptletu, wypisać normalny kod
HTMLa i powrócić do skryptletu. KaŜda instrukcja typu "while", "for" lub "if" kontroluje
równieŜ HTML. Jeśli HTML jest wewnątrz pętli, będzie wyświetlany raz na kaŜdy obrót
pętli.
Kolejny przykład mieszania skrypletów i HTMLa jest pokazany poniŜej -- zakładamy tu, ze
istnieje zmienna "hello" typu boolean. W zaleŜności od tego czy ustawimy ja na true czy
false, zostanie wyświetlony odpowiedni fragment kodu.
<%
if ( hello ) {
%>
<P>Hello, world
<%
} else {
%>
<P>Goodbye, world
<%
}
%>
Trochę trudne jest kontrolowanie wszystkich pootwieranych nawiasów oraz znaków początku
i końca skrypletu, ale przy odrobinie praktyki i dobrej metody formatowania moŜna nabrać
wprawy.
Dyrektywy JSP
W przykładach w poprzednich sekcjach uŜywaliśmy java.util.Date. Czy nie moŜna by
importować java.util.*?;
W JSP moŜna uŜyć instrukcji "import", ale syntaksa jest trochę inna od tej normalnie
uŜywanej w Javie. Popatrz na następujący przykład:
<%@ page import="java.util.*" %>
<HTML>
<BODY>
<%
System.out.println( " Sprawdzam date " );
Date date = new Date();
%>
Hello! The time is now <%= date %>
</BODY>
</HTML>
Pierwsza linia w powyŜszym przykładzie jest nazywana "dyrektywą". Dyrektywa JSP
zaczyna się sekwencją <%@.
UŜyta tutaj dyrektywa jest nazywana dyrektywą page. Dyrektywa page moŜe zawierać listę
wszystkich importowanych pakietów. Aby zaimportować ich więcej niŜ jeden, naleŜy
oddzielić poszczególne pakiety przecinkiem. Np.
<%@ page import="java.util.*,java.text.*" %>
Oprócz dyrektywy page istnieje wiele innych dyrektyw JSP. Najbardziej przydatne to
"include" i "taglib".
Dyrektywa include jest uŜywana do fizycznego załączania zawartosci innego pliku.
Załączany plik moŜe mieć rozszerzenie .html .jsp albo jakiekolwiek inne. Rezultat będzie taki
jakby nasz plik JSP zawierał w sobie załączony tekst. Aby zobaczyć tę dyrektywę w akcji,
stwórz nowy plik JSP
<HTML>
<BODY>
Going to include hello.jsp...<BR>
<%@ include file="hello.jsp" %>
</BODY>
</HTML>
Obejrzyj ten plik JSP w przeglądarce, a zobaczysz swój hello.jsp załączony w nowym
pliku JSP.
Deklaracje JSP
JSP które piszesz, zamienia się w deklaracje klasy. Wszystkie skryptlety są umieszczane
wewnątrz pojedynczej metody tej klasy.
MoŜesz równieŜ dodawać deklaracje metod i zmiennych do tej klasy. MoŜesz później
uŜywać zmiennych i metod z Twoich skryptletów i wyraŜeń.
Aby dodać deklarację, musisz uŜyć sekwencji <%! i %>, jak pokazano poniŜej.
<%@ page import="java.util.*" %>
<HTML>
<BODY>
<%!
Date theDate = new Date();
Date getDate()
{
System.out.println( "In getDate() method" );
return theDate;
}
%>
Hello! The time is now <%= getDate() %>
</BODY>
</HTML>
Przykład jest trochę przekombinowany, Ŝeby pokazać deklaracje metod i zmiennych.
Deklarowana zmienna typu Date theDate, oraz metoda getDate są dostępne w naszych
skryptletach i wyraŜeniach.
Ale... przykład nie działa tak jakbyśmy tego oczekiwali. Czas będzie taki sam, niezaleŜnie od
tego, ile razy przeładujesz stronę. To dlatego, Ŝe deklaracje są wyliczane tylko raz kiedy
strona jest ładowana. (Tak, jakbyś tworzył klasę i miał w niej deklarację inicjalizacji
zmiennej.)
Cwiczenie: Zmodyfikuj powyŜszy przyklad i dodaj nową funkcję computeDate która
reinicjalizuje theDate. Dodaj skryptlet, który wywołuje computeDate za kaŜdym razem.
Uwaga: Własciwym postępowaniem jest umieszczanie wszystkich zmiennych w obiektach
session lub request, które przekazują sobie dane pomiędzy stronami JSP.
Zmienne, które deklarujesz w skryptletach są dobre o ile potrzebujesz ich na zasięg jednego
skryptletu.
Tagi w JSP
Kolejnym istotnym elementem składni JSP są tagi. Tagi JSP nie uŜywają znaku <%, lecz <.
Tag JSP jest czymś w rodzaju tagu HTML. MoŜe on mieć "tag początkowy", "ciało tagu" i
"tag końcowy". Początkowy i końcowy tag uŜywają nazwy tagu, zamkniętej w znaki < i >.
Końcowy zaczyna się znakiem / umieszczonym po znaku <. Nazwy tagów zawierają znak
dwukropka w środku, część przed dwukropkiem opisuje typ tagu. Na przykład:
<some:tag>
body
</some:tag>
Jeśli tag nie potrzebuje ciała, początek i koniec mogą być wygodnie złączone ze sobą, tak jak
<some:tag/>
Tutaj poprzez zamknięcie tagu początkowego w ten sposób: /> zamiast znakiem >, kończymy
tag natychmiast i bez ciała. (Konwencja składniowa jest taka jak w XML.)
Tagi mogą być dwojakiego rodzaju: ładowane z zewnętrznej biblioteki, albo
predefiniowane. Tagi predefiniowane zaczynają się znakami jsp: . Na przykład,
jsp:include jest predefiniowanym tagiem który jest uŜywany do załączania innych stron.
JuŜ widzieliśmy dyrektywę include. jsp:include jest podobna. Ale zamiast ładowania tekstu
załączanego pliku w oryginalny, tak naprawdę wywołuje załączany cel w czasie wykonania
(sposób, w jaki przeglądarka mogłaby wywołać załączony cel. W praktyce, to jest raczej
symulowane zadanie niŜ "full round-trip" pomiędzy przeglądarką a serwerem). PoniŜej
pokazany jest przypadek uŜycia jsp:include
<HTML>
<BODY>
Going to include hello.jsp...<BR>
<jsp:include page="hello.jsp"/>
</BODY>
</HTML>
Spróbuj to zrobić i zobacz, co otrzymasz. Teraz zmień "jsp:include" na "jsp:forward" i
zobacz, jaka jest róŜnica. Te dwa predefiniowane tagi są często bardzo przydatne.
Cwiczenie Napisz JSP, które wykonuje forward lub include, zaleŜnie od zmiennej boolean
(wskazówka: Koncepcja połączenia HTML i skryptletow działa takŜe z tagami JSP!)
Sesje JSP
Przy pisaniu stron WWW bardzo przydatnym jest związać pewne dane z kaŜdym
odwiedzającym. Do tego celu uŜyte mogą zostać "session"s w JSP.
Sesja jest obiektem związanym z odwiedzającym. MoŜna do niego wrzucać pewne dane i
potem je odczytywać. Dla kaŜdego odwiedzającego tworzony jest nowy obiekt sesji.
Oto przykład jak moŜna w sesji zapamiętać imię odwiedzającego, a potem wyświetlić je
gdzieś indziej.
Najpierw formularz do wypełnienia. Nazwijmy go GetName.html
<HTML>
<BODY>
<FORM METHOD=POST ACTION="SaveName.jsp">
What's your name? <INPUT TYPE=TEXT NAME=username SIZE=20>
<P><INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>
Po wypełnieniu tego formularza odwiedzający zostanie przekierowany na stronę
"SaveName.jsp", która zachowa jego imię w obiekcie sesja. ZauwaŜ zmienną "session".
Jest ona kolejną zmienną, która jest dostępna w JSP, tak jak zmienne out i request. (W
dyrektywie @page moŜesz wskazać, Ŝe nie uŜywasz sesji, i wówczas zmienna "session" nie
będzie dostępna.)
<%
String name = request.getParameter( "username" );
session.setAttribute( "theName", name );
%>
<HTML>
<BODY>
<A HREF="NextPage.jsp">Continue</A>
</BODY>
</HTML>
SaveName.jsp zachowuje imię uŜytkownika w sesji i udostępnia link do kolejnej strony
NextPage.jsp.
NextPage.jsp pokazuje jak odzyskać zachowane imię.
<HTML>
<BODY>
Hello, <%= session.getAttribute( "theName" ) %>
</BODY>
</HTML>
Jeśli masz dwie róŜne przeglądarki (ale nie dwa okna tej samej przeglądarki), albo
uruchamiasz przeglądarki na dwóch komputerach, moŜesz umieścić jedno imię w jednej
przeglądarce, drugie imię w drugiej i oba imiona będą trzymane niezaleŜnie.
Obiekt sesji jest trzymany przez określony czas (timeout). Potem zakłada się, Ŝe uŜytkownik
nie odwiedza juŜ strony i obiekt sesji jest porzucany.
Ćwiczenie: Dodaj atrybut "age" do powyŜszego przykładu.