Java Server Pages

Prezentacja na zajęcia ZPP

Marta Adamska
Danuta Karwańska
Marianna Mysiorska
Katarzyna Zimnoch



Serwery JSP (1)

Jeśli nie masz dostępu do serwera obsługującego JSP, wówczas Twoim pierwszym krokiem do rozpoczęcia pracy z JSP jest ściągnięcie go z internetu. 
Jest wiele serverów dostępnych za darmo, jak chociażby:  
Blazix from Desiderata Software (1.5 Megabytes, JSP, Servlets and EJBs)
tomcat from jakarta, ale tez mozna znalezc w PUBLICU na rainbow.
ServletExec from New Atlanta/Unify (3.8 Megabytes, JSP and Servlets)
JRun from Allaire (11 Megabytes, JSP, Servlets and EJBs)
WebLogic from BEA Systems (44 Megabytes, JSP, Servlets and EJBs)
WebSphere from IBM (105 Megabytes, JSP, Servlets and EJBs)

Początki z JSP (2)

JSP po prostu umieszcza Javę wewnątrz stron HTML .  Można wziać stronę HTML i zmienić rozszeszenie na ".jsp" zamiast ".html".  To jest dobre ćwiczenie na początek.

W tym celu można utworzyć plik hello.html o tresci

<HTML>
<BODY>
Hello World!
</BODY>
</HTML>
potem zmienić rozszerzenie z ".html" na ".jsp" i zaladować go w przeglądarce.

Bedzie 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 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 jesli plik ulegnie zmianie, to konieczna bedzie jego rekompilacja.)

Oczywiscie, nie jest dobrym pomysłem pisanie stron zawierających jedynie HTML z rozszerzeniem .jsp :)  
 


Dodawanie dynamicznej zawartości (3)

Jak widzielismy, 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.


Scryptlety (4)

Wiadomo już, że wyrażenia javowe na stronach JSP należy umieszczać pomiędzy sekwencjami <%= i %> .

Ale trudno jest w ten sposob 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 wywolywane.  

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( "Evaluating date now" );
    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( "Evaluating date now" );
    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 wcisnię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( "Evaluating date now" );
    java.util.Date date = new java.util.Date();
%>
Hello!  The time is now
<%
    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 (5)

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 (6)

W przykładach w poprzednich sekcjach uzywalismy java.util.Date. Czy nie mozna 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( "Evaluating date now" );
    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 taglib omówiona zostanie pózniej.

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 (7)

JSP ktore piszesz, zamienia się w deklaracje klasy.  Wszystkie skryptlety są umieszczane wewnątrz pojedyńczej metody tej klasy.

Możesz również dodawać deklaracje metod i zmiennych do tej klasy.   Możesz później używac zmiennych i metod z Twoich skryptletów i wyrażeń.

Aby dodać deklarację, musisz użyc 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 dziala 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
(będą one przedstawione troche później), które przekazują sobie dane pomiędzy stronami JSP.
Zmienne, które deklarujesz w skryptletach są dobre o ile potrzebujesz ich na zasięg jedengo skryptletu.


Tagi w JSP (8)

Kolejnym istotnym elementem składni JSP sa tagi.  Tagi JSP nie uzywaja 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żywaja 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 sposob: /> 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 zaczynaja się znakami jsp: .  Na przykład, jsp:include jest predefiniowanym tagiem który jest używany do załaczania innych stron.

Już widzielismy 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 (sposob, w jaki przegladarka mogłaby wywołac załączony cel.  W praktyce, to jest raczej symulowane zadanie niż "full round-trip" pomiedzy przegladarka 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 rożnica.   Te dwa predefiniowane tagi są często bardzo przydatne.

Cwiczenie  Napisz JSP, które wykonuje forward lub include, zależnie od zmiennej boolean (wskazowka:  Koncepcja polaczenia HTML i skryptletow dziala takze z tagami JSP!)


Sesje JSP (9)

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.
 


Beans i formularze (10)

Formularze są jednym z najbardziej popularnych narzędzi służących do tworzenia stron internetowych.  JSP ułatwia korzystanie z formularzy.

Standardowy sposób obsługi JSP polega na zdefiniowaniu "bean".  Potrzebujemy tylko zdefiniować klase, która zawierać będzie pola takie jak pola formularza.  Pola klasy muszą mieć "setters"(atrybuty) pasujące do pół formularza.  Na przykład, zmodyfikujmy: GetName.html aby także przesyłać email adres i wiek.

Nowa wersja GetName.html wygląda następująco:

<HTML>
<BODY>
<FORM METHOD=POST ACTION="SaveName.jsp">
What's your name? <INPUT TYPE=TEXT NAME=username SIZE=20><BR>
What's your e-mail address? <INPUT TYPE=TEXT NAME=email SIZE=20><BR>
What's your age? <INPUT TYPE=TEXT NAME=age SIZE=4>
<P><INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>
Żeby przesyłać te dane, zdefiniujmy Java class z polami username", "email" i "age" i wprowadźmy metody"setter" (w sumie chodzi o akcesory:]) "setUsername", "setEmail" i "setAge", jak pokazaliśmy.  Metoda "setter" to metoda, ktora zaczyna sie od słów."set" kończymy ją nazwą pola klasy, które ustawia.  Nazwe tego pola piszemy z dużej litery  Dla pola "email", jego metoda "setter" wygląda "setEmail".  Metody getter definiujemy podobnie ze słowem get zamiast set.   Trzeba pamiętać, że setters  (i getters) muszą być public.
public class UserData {
    String username;
    String email;
    int age;

    public void setUsername( String value )
    {
        username = value;
    }

    public void setEmail( String value )
    {
        email = value;
    }

    public void setAge( int value )
    {
        age = value;
    }

    public String getUsername() { return username; }

    public String getEmail() { return email; }

    public int getAge() { return age; }
}
Nazwy metod muszą zawsze wyglądać jak to jest pokazane wyżej. Kiedy już raz zdefiniujemy klasę, skompilujemy trzeba się upewnić,czy jej ścieżka jest dostępna na serwerze.  Na serwerze może być także zdefiniowany specjalny katalog, gdzie możemy umieścić class bean.   Jeśli zmienimy ścieżke do niego, serwer musi być zatrzymany i zrestartowany,jeśli aktualnie pracuje. 

Teraz zmieńmy "SaveName.jsp", aby używać bean do przesyłania danych.

<jsp:useBean id="user" class="UserData" scope="session"/>
<jsp:setProperty name="user" property="*"/> 
<HTML>
<BODY>
<A HREF="NextPage.jsp">Continue</A>
</BODY>
</HTML>
Wszystko czego teraz potrzebujemy to jsp:useBean tag i jsp:setProperty tag!  Tag - useBean będzie szukał instancji "UserData" w tej sesji.   Jeśli znajdzie ją to ją uaktualni.  W przeciwnym przypadki stworzy nową instancję UserData (intancję UserData nazywamy bean), i umieszczamy w sesji.

Tag setProperty automatycznie przesyła dane wejściowe, łaczy nazwy z odpowiednimi metodami i umieszcza dane w bean! 

Zmodyfikujmy NextPage.jsp żeby odzyskać dane z bean.

<jsp:useBean id="user" class="UserData" scope="session"/> 
<HTML>
<BODY>
You entered<BR>
Name: <%= user.getUsername() %><BR>
Email: <%= user.getEmail() %><BR>
Age: <%= user.getAge() %><BR>
</BODY>
</HTML>
Zauważmy, że useBean tag powtarza się.  Bean jest dostępny przez nazwę zmiennej "user" z klasy "UserData".  Dane wprowadzane przez użytkownika są przechowywane w bean.

My właściwie nie potrzebujemy "SaveName.jsp", celem dla GetName.html może być NextPage.jsp, i dane będą ciągle dostępne, jeśli tylko dodamy taga jsp:setProperty.  Chociaż SaveName.jsp może przechwycić błąd i automatycznie przekazać go do request NextPage.jsp, lub poprosić użytkownika o poprawienie danych.


Tag libraries (biblioteki) (11)

Wprowadźmy metody rozszerzające tagi JSP.  Pozwalają one na dodawanie tagów podobnych do: jsp:include lub jsp:forward, ale także o innych prefiksach niż jsp: i z dodatkowymi możliwościami.

Żeby wprowadzić biblioteki tagów użyjemy np. Blazix - biblioteka tagów.  Biblioteka ta pochodzi z Blazix server, który można zainstalować za darmo do nauki i rozwoju:].  (Materiał dotyczący bibliotek dotyczy wszystkich bibliotek tagów).

Każda biblioteka tagów posiada swoją włąsną dokumentację.  Żeby używać tych bibliotek, używazmy dyrektyw "taglib", specyfikujących gdzie opis naszej biblioteki się znajduje.  Dla biblioteki Blazix ,  dyrektywa wygląda następująco:

<%@ taglib prefix="blx" uri="/blx.tld" %>
"uri" określa gdzie znaleźć opis biblioteki tagów. "Prefix" jest unikatowy dla biblioteki tagów.   Ta dyrektywa mówi , że będziemy używać biblioteki tagów zaczynając od blx:

Biblioteka Blazix wprowadza blx:getProperty tag. Ten tag może być używany żeby pozwolić użytkownikom na edytowanie danych.  W naszym pliku GetName.jsp dodamy i umieścimy formularz wewnątrz blx:getProperty.

Nowy GetName.jsp jest

<%@ taglib prefix="blx" uri="/blx.tld" %>
<jsp:useBean id="user" class="UserData" scope="session"/>
<HTML>
<BODY>
<blx:getProperty name="user" property="*">
<FORM METHOD=POST ACTION="SaveName.jsp">
What's your name? <INPUT TYPE=TEXT NAME=username SIZE=20><BR>
What's your e-mail address? <INPUT TYPE=TEXT NAME=email SIZE=20><BR>
What's your age? <INPUT TYPE=TEXT NAME=age SIZE=4>
<P><INPUT TYPE=SUBMIT>
</FORM>
</blx:getProperty>
</BODY>
</HTML>
Zauważmy, że blx:getProperty nie kończy się z /> , ale zamiast tego jest na końcu oddzielona linią </blx:getProperty>.  Aby wszystkie formularze były prawidłowo modyfikowane przez bibliotekę tagów, umieszczamy wszystkie pola formularza wewnątrz blx:getProperty

(Spróbuj umieścić link do GetName.jsp z NextPage.jsp, i zobaczysz, że dane z bean pokażą się automatycznie w wejściowym polu.)

Użytkownik może teraz edytować dane.

Ale ciągle mamy jeszcze trochę problemów.  Użytkownik nie może wyczyścić nazwy pola.  Ponadto jeśli użytkownik wprowadzi w pole "age" coś co nie jest typu integer pokaże się wyjątek Javy.

Użyjemy innego taga z Blazix żeby się tym zająć.  Blazix oferuje blx:setProperty tag, który można użyć, aby pozbyć się tej "niedogodnośći":].   blx:setProperty pozwala nam zdefiniować , metode przechwytującą wyjątek.  Jeśli pojawi się wyjątek możemy przechwycić wiadomość o błędzie i kontynuować proces.

Wersja SaveName.jsp, obsługuje błędy i także pokazuje znów GetName.jsp użytkownika użytkownikowi, żeby ten wprowadził dane poprawnie lub automatycznie przekazuje to do NextPage.jsp.

<%@ taglib prefix="blx" uri="/blx.tld" %>
<%!
    boolean haveError;
    StringBuffer errors;

    public void errorHandler( String field,
                              String value,
                              Exception ex )
    {
        haveError = true;
        if ( errors == null )
            errors = new StringBuffer();
        else
            errors.append( "<P>" );
        errors.append( "<P>Value for field \"" +
                     field + "\" is invalid." );
        if ( ex instanceof java.lang.NumberFormatException )
            errors.append( " The value must be a number." );
    }
%>
<%
    // Variables must be initialized outside declaration!
    haveError = false;
    errors = null;
%>
<HTML>
<BODY>
<jsp:useBean id="user" class="UserData" scope="session"/>
<blx:setProperty name="user"
     property="*" 
     onError="errorHandler"/> 
<%
    if ( haveError ) {
        out.println( errors.toString());
        pageContext.include( "GetName.jsp" );
    } else
        pageContext.forward( "NextPage.jsp" );
%>
</BODY>
</HTML>
Zauważmy, że haveError i errors musi być ponownie inicjalizowane za każdym razem dlatego, że są one inicjalizowane na zewnątrz deklaracji.

[Zwróćmy uwage także na użycie pageContext.include i pageContext.forward.  One są jak jsp:include i jsp:forward, ale są bardziej wygodne do użycia z Java blocks.   pageContext to kolejna pre-definiowana zmiennna , która ułatwia, że robienie pewnych operacji z Java blocks.]

Tutaj, jeśli pojawi się błąd w trakcie procesu blx:setProperty, wyświetli się błąd i wtedy załącz GetName.jsp , żebu użytkownik mógł poprawiać błędy.  Jeśli nie pojawią sie żadne błędy, automatycznie przekazujemy użytkownika do NextPage.jsp.

Tutaj jest wciąż problem z formularzami, jesli "age" pokaże się zainicjalizowany na zero zamiast pusty.   To można łatwo naprawić dodając "emptyInt=0" do obu tagów blx:getProperty i blx:setProperty (pola bean powinny być inicjalizowane na "0"). "0" nie jest odpowiednią wartością dla wieku dlatego możemy jej użyc do markowania pustych stringów.  Jeśli "0" okazałoby sie pooprawne zawsze możemy użyć. "emptyInt=-1" (i inicjalizowaz pola bean na -1.)

Kolejnym małym problemem jest, że "<HTML>" tag mnoży się jeśli pojawia się błąd, a my kończymy załączając "GetName.jsp".  Bardziej eleganckim rozwiązaniem byłoby usunąć out.println, i przekazać błędy z powrotem.

<%
    if ( haveError ) {
        request.setAttribute( "errors",
                 errors.toString());
        pageContext.forward( "GetName.jsp" );
    } else
        pageContext.forward( "NextPage.jsp" );
%>
Możemy wtedy stworzyć "request.getAttribute" in the GetName.jsp, i jeśli zwróci niepustą wartość, wyświetlić błąd.  

Ćwiczenie:  Przeczytaj dokumentację Blazix lub jakiejś innej biblioteki tagów i użyj kilku z nich.
 


Linki

więcej możesz przeczytac na stronach:
http://www.jsptut.com/
http://java.sun.com/developer/Books/javaserverpages/jsp_2ed/
http://www.google.pl