Marcin Paszkowski Czego potrzebujemy? Przegląd technologii JSP Do obsługi serwletów oraz JSP używamy kontenera. Czym on jest? Zapewnia on prosty mechanizm komunikacji pomiędzy serwletami a serwerem www. Zadania które wykonuje za nas kontener to m.in.: 1. buduje gniazda serwera 2. nasłuchuje komunikacje na odpowiednim porcie 3. zapewnia interfejs API pomiędzy serwerem www a kodem naszej aplikacji internetowej 4. zapewnia on wczytywanie odpowiednich klas, ich inicjalizacje, wywołanie odpowiednich metod 5. obsługuje wielowątkowość (wciąż jednak programista musi zadbać o ich bezpieczeństwo, Np. ich synchronizacja) 6. wymusza na nas stosowanie deskryptora rozmieszczeń - w pliku XML w których konfigurujemy mechanizmy zabezpieczeń bez ingerencji w kodzie Javy. 7. Uruchamia strony JSP. Tomcat to przykład takiego kontenera. Kiedy serwer www otrzymuje żądanie dotyczące serwletu serwer nie przekazuje tego żądania do serwletu ale właśnie do kontenera, w którym to serwlet jest umieszczony. Czym jest deskryptor rozmieszczenia? Określa on w jaki sposób należy wykonać serwlety tudzież strony JSP. Deskryptor rozmieszczenia to nic innego jak prosty dokument XML określający odwzorowanie adresów URL na serwlety. Przykład deskryptora zostanie zaprezentowany w przykładzie prostej aplikacji internetowej. Przykład wykorzystania modelu MVC dla serwletów i stron JSP MVC czyli model widok - kontroler to przykład wzorca projektowego. Główna idea tegoż to oddzielenie warstwy biznesowej od warstwy prezentacji. W przypadku tworzenia aplikacji internetowej z wykorzystaniem szeroko rozumianej technologii Javy ( czyli m.in. JSP, serwletów ) model MVC mógłby wyglądać tak: serwlet KONTROLER JSP WIDOK Kod Javy MODEL 1
Kontroler Pobiera z żądania dane wejściowe użytkownika. Nakazuje modelowi samoaktualizację i sprawia że stan zmienionego modelu jest dostępny dla widoku. Model Przechowuje logikę biznesową, stan aplikacji. Model może np. współpracować z bazą danych. Widok To warstwa prezentacji. Otrzymuje od kontrolera stan modelu. Przykład prostej aplikacji internetowej Poniższy przykład oparty jest na aplikacji opisanej w książce Bahama, Sierra i Batesa Head First Servlets and JSP. W niniejszym przykładzie korzystamy z kontenera Tomcat. Oto struktura katalogów naszej aplikacji: TOMCAT webapps projekt WEB-INF form.html wynik.jsp classes web.xml com example web model WyborPiwa.class EkspertPiwny.class TOMCAT katalog domowy Tomcata ( Np. jakarta-tomcat-5.0.19 ) Webapps katalog wymagany przez kontener odgórnie Projekt nazwa naszej aplikacji ( każdy projekt w Tomcat musi mieć swój katalog ) Web.xml nasz deskryptor rozmieszczenia znajduje się w katalogu: WEB-INF. Jest to wymagane! 1. Tworzymy kod formularza w HTML (form.html): <html><body> <h1 align="center">strona wyboru piwa</h1> <fomr method="post" action="wybierzpiwo.do"> Wybierz właściwości piwa <p> Kolor: <select name="kolor"> <option>jasny 2
<option>żółty <option>brązowy <option>ciemny </select> <br><br> <center> <input type="submit"> </center> </body></html> Wyjaśnienie: WybierzPiwo.do jest to nazwa, którą wykorzystujemy do wywołania odpowiedniego serwletu. Jest to nazwa logiczna, która nie ma swojego odzwierciedlenia w strukturze plików. Jest ona znana klientom aplikacji. kolor w nim przykazujemy informacje z formularza do konkretnego skryptu. 2. Tworzymy deskryptor rozmieszczenia (web.xml): <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>r3 Piwo</servlet-name> <servlet-class>com.example.web.wyborpiwa</servlet-class> </servlet> <servlet-mapping> <servlet-name>r3 Piwo</servlet-name> <servlet-class>/wybierzpiwo.do</servlet-class> </servlet-mapping> </web-app> Wyjaśnienie: R3 Piwo sztuczna nazwa wykorzystywana w ramach tego samego pliku w tym przypadku Web.xml. com.example.web.wyborpiwa nazwa pliku klasy serwletu. ( umieszczona ona jest w pakiecie ). WybierzPiwo.do klient w ten sposób odwołuje się do naszego serwletu. ( końcówka do nie jest obowiązkowa jednak przyjęło się ją nieformalnie stosować ). 3. Budowa klasy modelu ( EkspertPiwny.java ) czyli Java w czystej postaci: package com.example.model; import java.util.*; public class ExpertPiwny public ArrayList getmarki( String kolor ) ArrayList<String> marki = new ArrayList<String>(); if( kolor.equals( "bursztynowy" ) ) 3
else marki.add( "Jack Amber" ); marki.add( "Red Moode" ); marki.add( "Jail Pale Ale" ); marki.add( "Gout Stout" ); return (marki); 4. Budowanie klasy serwletu tworzenie kontrolera ( WyborPiwa.java ): package com.example.web; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import model.expertpiwny; public class WyborPiwa extends HttpServlet public void dopost( HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException String c = request.getparameter( "kolor" ); ExpertPiwny be = new ExpertPiwny(); List wynik = be.getmarki( c ); request.setattribute( "styles", wynik ); requestdispatcher view = request.getrequestdispatcher( "wynik.jsp" ); view.forward( Request, response ); Wyjaśnienie: dopost skoro formularz wysyła żądanie używając atrybutu method= POST, analogicznie korzystamy z odpowiednika POST-a w serwecie czyli metody dopost. String c = Request.getParameter( kolor ) argument tej metody kolor odpowiada użytej przy tworzeniu formularza wartości atrybutu name znacznika <select>. package. Request.setAttribute( styles, wynik ) - dodajemy do obiektu żądania, który będzie wykorzystywany przez stronę JSP. Będzie ona wykorzystywała atrybut styles. requestdispatcher view = Request.getRequestDispatcher( Wynik.jsp ) tworzony jest egzemplarz klasy, przekazujący żądanie do właściwej strony JSP. 4
view.foraward( Request, response ) wymuszamy na kontenerze zaangażowania wskazanej strony JSP. 5. Budowanie widoku JSP (wynik.jsp) <%@ page import="java.util.*" <html> <body> <h1 align="center">jsp z rekomendacjami dotyczącymi piwa</h1> <p> <% List styles = (List)request.getAttribute("styles"); Iterator it = styles.iterator(); while( it.hasnext() ) out.print( "<br>sprobuj: " + it.next() ); </body> </html> Wyjaśnienie: List styles = (List)Request.getAttribute( styles ) w tym miejscu pobieramy atrybut z obiektu żądania. Uruchamianie serwletów i JSP ( na przykładzie naszej aplikacji ) 1. Kompilacja pliku EkspertPiwny.java : javac -classpath C:\jakarta-tomcat-5.0.19\common\lib\servlet-api.jar:classes:.-d src\com\example\model\ekspertpiwny.java Utworzony plik: EkspertPiwny.class załadowany jest dzięki parametrowi d do folderu classes. 2. Kompilacja pliku WyborPiwa.java : javac -classpath C:\jakarta-tomcat-5.0.19\common\lib\servlet-api.jar:classes:.-d src\com\example\web\wyborpiwa.java Utworzony plik: WyborPiwa.class załadowany jest dzięki parametrowi d do folderu classes. 3. Uruchamiamy Tomcata poleceniem startup.bat 4. Plik JSP automatycznie jest kompilowany przez kontener po otrzymaniu pierwszego żadania dotyczącego naszej aplikacji. Zrzuty działającej aplikacji Po wpisaniu w okno przeglądarki polecenia: http://localhost:8080/projekt/form.html - odpalimy nasz program: 5
Widok po otwarciu pliku fomr.html Po wybraniu koloru aplikacja powinna na zarekomendować konkretne piwo Więcej o technologii JSP Strona JSP jest tłumaczona na serwlet. Wykonuje to za nas kontener WWW. Na początku więc kod strony JSP tłumaczony jest na postać kodu źródłowego klasy Java ( *.java ), po czym następuje kompilacja na postać serwletu. Dyrektywa page służy do importowania niezbędnych pakietów używanych na stronie JSP: Np. package pakiet; public class licznik //ciało klasy public static int getliczba() //ciało metody Aby teraz wykorzystać klasę Javy w naszym pliku JSP, wykonujemy: <%@ page import="pakiet.* <html><body> <% out.println( licznik.getliczba() ); </body></html> Aby zaimportować wiele pakietów piszemy: <%@ page import="pakiet.*, java.util.*. Znaczek <%@ - oznacza dyrektywę. W powyższym przykładowym kodzie JSP zbędne jest użycie metody println: wystarczy napisać: <%= licznik.getliczba() - a wynik i tak będzie wyświetlony na stronie. Są to tzw. wyrażenia tłumaczone one są na argumenty wywołań out.print(). Skryptlet: <% 6
Dyrektywa <%@ Wyrażenie <%= Pomiędzy <%! i możemy deklarować w kodzie JSP zmienne jaki i metody które są umieszczane w wygenerowanej klasie serwletu. Np. <html><body> <%! int podwojenie() liczba = liczba * 2; return liczba; <%! int liczba = 1; Liczba wynosi: <%= podwojenie() </body></html> W kodzie JSP można umieszczać dwa rodzaje komentarzy: <!--komentarz HTML-- > i <%-- komentarz JSP -- Krótki przegląd standardowej biblioteki znaczników (JSTL) JSTL to stworzona przez kogoś i upakowana biblioteka znaczników, z których możemy w prosty sposób korzystać w naszych stronach JSP. Okazuje się że można również definiować swoje znaczniki. Przykład: Kod serwletu:... String[] listafilmow = "Solaris", "Kroll", "Psy" ; request.setattribute( "listafilmow", listafilmow );... Kod JSP: <table> <% String[] elementy = (String[])request.getAttribute( "listafilmow" ); String zmienna = null; for( int i=0 ; i<elementy.length ; i++ ) zmienna = elementy[ i ]; <tr><td><%= zmienna </td></tr> <% </table> Wykorzystując jednak bibliotekę znaczników nasz kod może wyglądać tak: Kod JSP z wykorzystaniem JSTL: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" <html><body> <strong>lista filmów</strong> <br> <table> 7
<c:foreach var="film" items="$listafilmow" <tr> <td>$film</td> </tr> </c:foreach> </table> </body></html> Opis niektórych znaczników z biblioteki JSTL: <c:foreach> Jest on jakby odpowiednikiem pętli for. Powtarza on się dla każdego elementu czy to tablicy, odpowiedniej kolekcji tudzież łańcucha w postaci separatora. Znacznik ten możemy zagnieżdżać. <c:if> Odpowiednik kluczowego słowa if dostępnego w większości języków programowania. Znacznik <c:choose> oraz <c:when> i <c:otherwise> Jest to jakby odpowiednik instrukcji swich, z tym że wybór może być tylko jeden. Np. <c:choose> <c:when test= $preferencje == bialy > Lubisz kolor biały! </c:when> <c:when test= $preferencje == czerwony > Lubisz kolor biały! </c:when> <c:otherwise> Nie lubisz czerwonego i białego? </c:otherwise> </c:choose> <c:set> Znacznik ten służy np. do dodania nowego elementu dla klasy Map. (Nie możemy dodać elementów do list lub tablic). <c:import> Np. <c:import url= http://www.buldog.pl/index.html > - czyli dodaje do bieżącej strony zawartość pliku wskazanego za pomocą atrybutu url. Przy czym mammy możliwość dołączania zasobów spoza obszaru kontenera. Podsumowanie Referat ten nie miał na celu dokładnego opisania technologii JSP jak i związanych z nim technologii pokrewnych. Ma on jedynie na celu zarysowanie krótki i szybki wgląd na możliwości programowania serwletów i stron JSP. W niniejszym referacie oparłem się na książce Head First Serwlet and JSP i wszystkich zainteresowanych odsyłam do tej pozycji, zaznaczając jednak że trzeba znać choćby podstawy języka Java by przystąpić do lektury tegoż. W tejże pozycji możemy poznać szczegóły programowania serwletów, JSP, związaną z nimi podstawą języka EL, dokładnie zapoznać się z biblioteka JSTL oraz nauczyć się tworzyć własne znaczniki i wiele innych rzeczy. 8