Plan Przetwarzanie dokumentów XML i zaawansowane techniki WWW Wykład 09 T. Romańczukiewicz Jagiellonian University 2009/2010
Plan Plan 1 Serwlety
Plan Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele 1 Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dzielenie zasobów Instalacja w Tomcacie Podsumowanie
XML, poprawnie sformuowanie Sposoby opisu XML DTD XML Schema XPATH Sposoby prezentacji CSS XSLT DOM SAX JAXB Serwlety
Serwlet Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Serwlet Serwlety sa małymi programami wykonywanymi w kontenerze serletów. Kontener serwletów działa podobnie jak serwer www, tzn. obsługuje zapytania klientów oraz generuje odpowiedzi. Kontener serwletów może być samodzielna usługa, lecz częściej pracuje jako moduł serwera www Rozszerzaja możliwośći serwera. Serwlety nie maja interfejsu użytkownika, komunikuja się z przegladark a za pomoca protokołu HTTP. Otrzymuja one od serwera komplet informacji zebranych z interakcyjnych elementów strony (zwykle z pól formularza) i po ich przetworzeniu dostarczaja gotowa stronę WWW - przesyłana przez serwer do użytkownika. Moga korzystać ze standardowych klas Javy (z VM), klas wchodzacych w skład Servlet API: javax.servlet.* i javax.servlet.http.* oraz ewentualnie z dodatkowych bibliotek zainstalowanych na serwerze.
Najczęstsze zastosowania przetwarzanie formularzy forwarding (przekierowanie do innego servletu) wyświetlania wyników zapytań do baz danych (strony JSP) Miejsce serwletów w aplikacjach J2EE serwlety to rozszerzenie serwera WWW blisko interfejsu użytkownika: zorientowane na żadanie/odpowiedź (request/response) serwlety działaja w odpowiedzi na żadania klienta sa interfejsem do serwera aplikacyjnego/bazy danych/ejb pełnia rolę kontrolera w schemacie Model-View-Controller, za widok odpowiedzialne sa strony JSP (czyli kod Javy imieszczony w pliku html), model to EJB w serwletach zaleca się umieszczanie tylko lekkich funkcji biznesowych, ale w małych aplikacjach cała logika może być w serwletach i JSP
Servlety a skrypty CGI Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Tradycyjnie funkcjonalność do stron WWW dodawana jest przy wykorzystaniu skryptów Common Gateway Interface. Interfejs CGI (niezależny od języka) pozwala na otwieranie nowego procesu na serwerze, który pobiera informacje o zapytaniu poprzez zmienne środowiskowe Wynik wypisywany jest do standardowego strumienia Każde zapytanie jest obsługiwane przez osobna instancję programu lub skryptu CGI Zalety serwletów Serwlety nie działaja w osobnym procesie - nie sa zatem tworzone procesy dla każdego zapytania Serwlet pozostaje w pamięci pomiędzy zapytaniami. CGI musi być każdorazowa ładowane do pamięci, często razem z interpreterem Jest tylko jedna instancja serwletu obsługujaca wszystkie zapytania Bezpieczeństwo: serwlety można uruchamiać przy pomocy restrykcyjnej maszyny Sandbox
Przykład Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Listing 1: Przykład kodu serwletu 1 import java.io.ioexception; 2 import java.io.printwriter; 3 import javax.servlet.servletexception; 4 import javax.servlet.http.httpservlet; 5 import javax.servlet.http.httpservletrequest; 6 import javax.servlet.http.httpservletresponse; 7 8 public class SimpleServlet extends HttpServlet 9 { 10 public void doget(httpservletrequest request, HttpServletResponse response) 11 throws ServletException, IOException { 12 PrintWriter out; 13 14 response.setcontenttype("text/html"); 15 16 out = response.getwriter(); 17 out.println("<html><head><title>"); 18 out.println("hello world servlet"); 19 out.println("</title></head><body>"); 20 out.println("<h1>" + title + "</H1>"); 21 out.println("<p>this is output from SimpleServlet."); 22 out.println("</body></html>"); 23 out.close(); 24 } 25 }
Komunikacja z klientem Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele przedefiniowanie metod doget, dopost, doput, dodelete. Te metody sa wywoływane przez metodę service zdefiniowana w Servlet przy każdym żadaniu do serwera dotyczacym serwletu. dane od klienta (przegladarki) sa w obiekcie HttpServletRequest. Ważne metody obiektu request: getparameter - zwraca parametr, np. z formularza getcookies - daje ciasteczka getsession - podaje obiekt sesji getreader (dla danych tekstowych) getinputstream (dla danych binarnych) dane do klienta symbolizuje obiekt HttpServletResponse Ważne metody obiektu response: getwriter (dane tekstowe) getoutputstream (dane binarne)
Przykład Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Listing 2: Przykład komunikacji - html 1 <html> 2 <head><title>formularz</title></head> 3 <body> 4 <form action="/trom/test" method="post"> 5 Podaj tekst: <input type="text" name="tekst" value=""> 6 </form> 7 </body> 8 </html> Listing 3: Przykład komunikacji 1 import java.io.*; 2 import javax.servlet.*; 3 import javax.servlet.http.*; 4 5 public class TestServlet extends HttpServlet { 6 7 public void dopost(httpservletrequest request, 8 HttpServletResponse response) 9 throws ServletException, IOException { 10 PrintWriter out; 11 String tekst;
Przykład Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Listing 4: Przykład komunikacji cd 12 response.setcontenttype("text/html"); 13 out = response.getwriter(); 14 out.println("<html><head><title>wyniki z formularza"); 15 out.println("</title></head><body>"); 16 tekst = request.getparameter("tekst"); 17 if (tekst!= null) 18 out.println("z formularza otrzymalem: " + tekst); 19 else 20 out.println("brak danych z formularza"); 21 out.println("</body></html>"); 22 out.close(); 23 } 24 25 public void doget(httpservletrequest request, 26 HttpServletResponse response) 27 throws ServletException, IOException { 28 PrintWriter out; 29 String tekst; 30 31 response.setcontenttype("text/html"); 32 out = response.getwriter(); 33 out.println("<html><head><title>uwaga</title>"); 34 out.println("</head><body>"); 35 out.println("ten serwlet nie obsluguje metody GET!"); 36 out.println("</body></html>"); 37 out.close(); 38 } 39 40 }
Serwlet to instancja klasy, która implementuje interfejs javax.servlet.servlet Większość serwletów rozszerza jedna ze standardowych implementacji tego interfejsu: javax.servlet.genericservlet i javax.servlet.http.httpservlet Serwers aplikacji ładuje klasę serwletu i wywołuje bezargumentowy konstruktor Następnie wywoływana jest metoda serwletu init(servletconfig config) Uwaga: serwlety korzystajace z javax.servlet.genericservlet i javax.servlet.http.httpservlet powinny wywoływać super.init(config) na poczatku metody init Metoda init wywoływana jest raz podczas cyklu życia serwletu. jeżeli coś pójdzie nie tak to należy rzucić wyjatek UnavailableException Metoda serviceservletrequest req, ServletResponse res) jest wywoływana po zakończeniu init dla każdego zapytania servletu. Może się zdarzyć, że metoda ta będzie wywoływana wielokrotnie w tym samym czasie trzeba zapewnić wykluczanie ręcznie, np. używajac zmiennych/metod synchronized Na końcu cyklu życia serwletu wywoływana jest metoda destroy() Uwaga! Jeżeli metoda do[getpost] wykonuje się długo, to trzeba zadbać o jej zakończenie. Jeżeli serwlet uruchamiał watki, to też trzeba je przerwać.
Protokół HTTP, zapytanie-odpowiedź Zapytanie HTTP składa się z metody zapytania, URI, nagłówka i ciała (pustego badź nie) Odpowiedź zawiera kod resultatu, nagłówek i ciało Metoda service() wysyła zapytanie do różnych metod Javy dla różnych zapytań HTTP Rozpoznawane sa metody standardu HTTP/1.1: GET, HEAD, PUT, POST, DELETE, OPTIONS i TRACE Odpowiednia metoda XXX zapytania HTTP jest przekazywana do doxxx(httpservletrequest req, HttpServletResponse res) W praktyce wykorzystuje się metody doget, doput, dopost, dodelete subclass of HttpServlet overrides one or more of these methods to provide a meaningful implementation.
Utrzymywanie stanu (session tracking) To jedna z najważniejszych zalet serwletów. Nie ma tego w CGI. Schemat: HttpSession session = request.getsession(true); (czytanie/pisanie) Klasa ref_obiektu1 = new Klasa(); (pisanie) session.putattribute("dluga.nazwa_atr", ref_obiektu1); (pisanie) Klasa ref_obiektu2 = (Klasa)session.getAttribute("dluga.nazwa_atr"); (czytanie) Cechy: Wkładanie i wyjmowanie obiektów z sesji nie ma nic wspólnego z interfejsem serializable. Obiekty nie sa nigdzie składowane, tylko istnieja w pamięci kontenera. Metody operuja na referencjach. Po odczytaniu referencji metoda getattribute operujemy już na oryginalnym (jedynym!) obiekcie. Po odczytaniu atrybutu trzeba sprawdzić czy jest równy null, jeżeli tak to trzeba utworzyć nowy obiekt (uwaga na wielowatkowość). Sesje działaja standardowo na ciasteczkach. W ciasteczku jest tylko id sesji, reszta siedzi w pamięci kontenera. Jeżeli przegl adarka nie obsługuje ciasteczek to trzeba używać metody encodeurl(). Gdy serwlet ma wyświetlić link do drugiego serwletu to w metodzie doget() trzeba umieścić:
Użycie sesji Serwlety Przypomnienie Serwlety - wstęp Wstęp Możliwości serwletów Dziele Listing 5: Przykład użycia sesji 1 import java.io.*; 2 import javax.servlet.*; 3 import javax.servlet.http.*; 4 5 public class DodajProdukt extends HttpServlet { 6 7 public void doget(httpservletrequest request, HttpServletResponse response) 8 throws ServletException, IOException { 9 HttpSession session = request.getsession(true); 10 Koszyk koszyk = (Koszyk) session.getattribute("pl.zakupy.koszyk"); 11 12 if (koszyk == null) { 13 koszyk = new Koszyk(); 14 session.setattribute("pl.zakupy.koszyk", koszyk); 15 } 16 17 koszyk.dodaj(request.getparameter("produkt")); 18 RequestDispatcher dispatcher = 19 getservletcontext().getrequestdispatcher("/wyswietl_koszyk.jsp"); 20 if (dispatcher!= null) 21 dispatcher.forward(request, response); 22 } 23 } Po modyfikacji koszyka nie trzeba go specjalnie zapisywać do sesji. W skrypcie /wyswietl_koszyk.jsp wyświetlana jest zawartość koszyka.
Użycie sesji jest wskazane, jednak można też używać cookies: Listing 6: Ciasteczka 1 public void doget(httpservletrequest request, HttpServletResponse response) 2 throws IOException, ServletException 3 { 4 response.setcontenttype("text/html"); 5 PrintWriter out = response.getwriter(); 6 7 / / p r i n t o u t c o o k i e s 8 9 Cookie[] cookies = request.getcookies(); 10 for (int i = 0; i < cookies.length; i++) { 11 Cookie c = cookies[i]; 12 String name = c.getname(); 13 String value = c.getvalue(); 14 out.println(name + " = " + value); 15 } 16 17 / / s e t a c o o k i e 18 19 String name = request.getparameter("cookiename"); 20 if (name!= null && name.length() > 0) { 21 String value = request.getparameter("cookievalue"); 22 Cookie c = new Cookie(name, value); 23 response.addcookie(c); 24 } 25 }
Dzielenie zasobów między serwlety (ServletContext) ServletContext context = getservletcontext(); (czytanie/pisanie) Klasa ref_obiektu1 = new Klasa(); (pisanie) context.setattribute("dluga.nazwa_atr", ref_obiektu1); (pisanie) Klasa ref_obiektu2 = context.getattribute("dluga.nazwa_atr"); (czytanie) Przechowywanie podobne jak w sesji, ale te same obiekty sa dostępne dla wszystkich serwletów na serwerze (w kontenerze). Uwaga na nazwy atrybutów, żeby dwie różne aplikacje nie korzystały z tego samego atrybutu. Listing 7: Przykład użycia kontekstu 1 public class WyswietlDane extends HttpServlet { 2 3 public synchronized void init() throws ServletExcpetion { 4 5 BazaDanych bd = (BazaDanych) 6 getservletcontext().getattribute("pl.sklep.bd.baza"); 7 8 if (bd == null) { 9 bd = new BazaDanych("http://pulsar", "scott", "tiger"); 10 getservletcontext().setattribute("pl.sklep.bd.baza", bd); 11 } 12 } 13... 14 }
Serwlety maja dostęp do innych serwletów w tym samym kontekście (zazwyczaj katalogu), reprezentowanym poprzez javax.servlet.servletcontext. ServletContext jest dostępny poprzez metodę getservletcontext obiektu ServletConfig Listę dostępnych servletów można uzyskać poprzez metodę getservletnames Po otrzymaniu referencji do innego serwletu można wywoływac jego metody. Należy jednak zrzutować dany obiket na typ żadanej klasy (ClassLoader) Przykład Servlet FooServlet chce wywołać metodę public void bar() serwletu BarServlet
Listing 8: FooServlet.java 1 public class FooServlet extends HttpServlet 2 { 3 protected void doget(httpservletrequest req, 4 HttpServletResponse res) 5 throws ServletException, IOException 6 { 7... 8 ServletContext context = getservletconfig().getservletcontext(); 9 BarInterface bar = (BarInterface)context.getServlet("BarServlet"); 10 bar.bar(); 11.. 12 } 13... 14 } 15 \begin{lstlisting} Listing 9: BarInterface 1 public interface BarInterface 2 { 3 public void bar(); 4 }
Listing 10: BarServlet.java 1 public class BarServlet extends HttpServlet implements BarInterface 2 { 3 public void bar() 4 { 5 System.err.println(""bar() called""); 6 } 7... 8 }
Instalacja serwletu w Tomcacie Zakładamy, że Tomcat już działa (np. zintegrowany z Apachem) i korzysta z katalogu #TOMCAT_HOME. Uwaga: pozostałe ścieżki i nazwy sa b. ważne. Kompilujemy serwlet korzystajac z biblioteki servlet.jar: javac -classpath #TOMCAT_HOME/lib/servlet.jar Test.java Plik Test.class kopiujemy do katalogu #TOMCAT_HOME/webapps/testkatalog/WEB-INF/classes Tworzymy plik #TOMCAT_HOME/webapps/testkatalog/WEB-INF/web.xml zawierajacy informacje o serwlecie Listing 11: web.xml 1 <!DOCTYPE web-app 2 PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" 3 "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> 4 5 <web-app> 6 <servlet> 7 <servlet-name> test_serw </servlet-name> 8 <servlet-class> Test </servlet-class> 9 </servlet> 10 11 <servlet-mapping> 12 <servlet-name> test_serw </servlet-name> 13 <url-pattern> /test </url-pattern> 14 </servlet-mapping> 15 </web-app>
Serwlet można uruchomić poprzez http://localhost:8180/testkatalog/test Port obsługujacy Tomcata można odczytać np z pliku #TOMCAT_HOME/conf/server.xml jako atrybut znacznika <Connector port="8180"... >. Inne popularne porty to 8080, 8009
Podsumowanie Serwlety - niewielkie programy javowe (podobnie jak aplety) ale wykonujace się po stronie serwera Sa alternatywa dla CGI; tak samo można używać do obsługi formularzy, przysłania danych itp. Serwlety korzystaja z protokołu zapytań HTTP Request (get, post itp) Pozostaja w pamięci przez cały czas, nie ma potrzeby ładowania ich przy każdym zapytaniu - metoda init() działa tylko raz Moga obsługiwać sesje, ciasteczka Moga się ze soba komunikować