Przegląd innych rozwiązań szkieletowych dla J2EE
Transkrypt
Przegląd innych rozwiązań szkieletowych dla J2EE
420 Przegląd innych rozwiązań szkieletowych dla J2EE 421 Plan prezentacji • • • • WebWork Tapestry Turbine AppFuse 422 WebWork 423 WebWork • Technologia szkieletowa ułatwiająca konstrukcję aplikacji J2EE zgodnych z Model-View-Controller • Konkurencja dla Struts • Swoboda wyboru technologii dla komponentów View • WebWork nie jest bezwzględnie uzależnione od J2EE 424 Architektura WebWork odbiera żądania przeglądarki (element gotowy) przekazuje odpowiedź do przeglądarki ServletDispatcher Result View WebWork2 przechwytuje żądanie i odpowiedź Interceptor1 Interceptor2 obsługuje żądanie, generuje odpowiedź Action xwork.xml plik konfiguracyjny, opis ścieżek nawigacyjnych XWork 425 Architektura WebWork: Action • • • • Klasa Java implementowana przez programistę Implementuje reakcję na żądanie przeglądarki Koordynuje obsługę żądania (Controller) Odbiera parametry wywołania i przekazuje je do komponentów modelu 426 Architektura WebWork: Action • Implementacja: – klasa Java implementująca interfejs Action – zawiera metodę execute() – zawiera metody set/get dla parametrów wywołania import com.opensymphony.xwork.Action; public class HelloWorldAction implements Action{ dane modelu String greeting; dostęp do danych modelu public String getGreeting() { return greeting; } metoda obsługi żądania public String execute() throws Exception { greeting = "Hello World!"; return SUCCESS; } } sygnał nawigacyjny 427 Architektura WebWork: Action • Reprezentacja modelu: – model zintegrowany z klasą Action – model implementowany przez oddzielną klasę public class Akcja1 implements Action { public String getFirstName(){} public setFirstName(...){} public String getLastName(){} public class Akcja1 implements Action { public Pracownik getPracownik(){} public setLastName(...){} public setPracownik(...){} } } public class Pracownik { public String getFirstName(){} public setFirstName(...){} public String getLastName(){} public setLastName(...){} } 428 Architektura WebWork: Result View • Komponent prezentacyjny implementowany przez programistę • Dostępne technologie: JavaServer Pages, Velocity, XML, Free Marker, JasperReports • Posiada dostęp do danych modelu <%@ taglib prefix="ww" uri="webwork" %> <html> <head> <title>WebWork Example</title> </head> <body> <p><ww:property value="greeting"/></p> </body> </html> greetings.jsp biblioteka znaczników WebWork do użycia w JSP wyświetla dane modelu powiązanego z obsługą żądania 429 Architektura WebWork: Result View • Biblioteka znaczników JSP • Przykładowe znaczniki: – – – – – – – <textfield label="Nazwa użytkownika" name="username"/> <password label="Hasło" name="password"/> <property value="atrybut"/> <submit value="Login"/> <if test="warunek"></if> <iterator value="elementy"></iterator> itd. 430 Architektura WebWork: Interceptor • Klasa Java implementowana przez programistę • Wywoływana przed/po obsłudze żądania przez klasę Action • Umożliwia filtrowanie, modyfikację, rejestrację, transformację żądań i odpowiedzi • Przykłady zastosowań: – nawiązywanie połączenia z bazą danych – ochrona dostępu do aplikacji • Implementacja: – klasa Java implementująca interfejs Interceptor – zawiera metody intercept(), before(), after() 431 Architektura WebWork: Interceptor Interceptor implementujący metodę intercept() przechwytuje każde żądanie, jawnie wykonuje kod Action (lub kod kolejnego Interceptora): public class TimerInterceptor implements Interceptor { ... public String intercept(ActionInvocation dispatcher) ...{ long startTime = System.currentTimeMillis(); String result = dispatcher.invoke(); long exTime = System.currentTimeMillis() - startTime; log.info("Czas wykonania:" + exTime + "ms."); return result; } } przechwytuje żądanie wywołuje następny element w łańcuchu przepływu sterowania 432 Architektura WebWork: Interceptor Interceptor implementujący metody before()/after() jest uruchamiany przed/po wykonaniem kodu Action (lub kolejnego Interceptora). public class LoggingInterceptor extends AbstractInterceptor { ... protected void before(ActionInvocation invocation) ... { log.info("Rozpoczęcie obsługi żądania"); } protected void after(ActionInvocation invocation, String result) ...{ log.info("Zakończenie obsługi żądania); } } wywoływane przed przekazaniem żądania do kolejnego elementu w łańcuchu wywoływane po zakończeniu obsługi żądania przez kolejny element w łańcuchu 433 Architektura WebWork: plik xwork.xml • Definiuje strukturę całej aplikacji • Zawiera deklaracje klas Action, klas Interceptor, modułów Result View • Opisuje ścieżki nawigacyjne <interceptor name="int0" class="LoggingInterceptor"/> <action name="hello" class="HelloWorldAction"> <result name="success" type="dispatcher"> <param name="location">/greetings.jsp</param> </result> <interceptor-ref name="debugStack"/> <interceptor-ref name="defaultStack"/> <interceptor-ref name="int0"/> </action> deklaracja klasy Interceptora stos Interceptorów deklaracja klasy Action na sygnał "success" skocz do greetings.jsp Przykładowa aplikacja: przebieg sterowania http://.../hello.action ServletDispatcher xwork.xml LoggingInterceptor.before() HelloWorldAction.execute() HelloWorldAction.getGreetings() success LoggingInterceptor.after() success greetings.jsp 434 435 Walidacja parametrów wywołania • Deklaratywna – – – – – – RequiredString - pole ma wartość o niezerowej długości IntRange - liczba całkowita w zadanym przedziale DateRange - data w zadanym przedziale Email - adres e-mail o poprawnej strukturze URL - adres URL o poprawnej strukturze Expression/FieldExpression - wyrażenie OGNL zwraca true • Implementowana za pomocą klas walidatorów • Implementowana za pomocą klas Interceptor 436 Walidacja parametrów wywołania Deklaratywna walidacja parametrów wywołania <validators> nazwa parametru wywołania <field name="username"> <field-validator type="requiredstring"> <message>Podaj nazwę użytkownika!</message> reguła walidacji </field-validator> </field> komunikat <field name="confirm"> wyświetlany w <field-validator type="fieldexpression"> przypadku <param name="expression"> naruszenia confirm == password.equals(confirm) reguły walidacji </param> <message>Niepoprawne hasło!</message> </field-validator> </field> </validators> <nazwa_klasy_Action>-validation.xml 437 Język wyrażeń OGNL • OGNL: Object Graph Navigation Language • Język wyrażeń opracowywany w ramach projektu Open Source - www.ognl.org • Przykłady: Wyrażenie OGNL Wynik employee.name getEmployee().getName() name.toString getName().toString() employee.categories[0] Pierwszy element kolekcji categories stanowiącej atrybut obiektu employee name in {null, "abc"} name ma warość nul lub "abc" categories.{name} na każdym elemencie kolekcji categories wywołuje metodę getName(), zwraca nową kolekcję wyników 438 Tapestry 439 Tapestry • Komponentowe środowisko szkieletowe służące do konstrukcji aplikacji J2EE • Rozpowszechniane na zasadach open-source • Stara się upodobnić proces tworzenia aplikacji internetowych do procesu tworzenia tradycyjnych aplikacji z graficznym interfejsem użytkownika • Wspiera architekturę Model-View-Controller • Oparte bezpośrednio na Servlet API 440 Elementy Model-View-Controller • Komponenty Model: – samodzielne klasy Java – możliwość integracji z komponentami Controller • Komponenty View: – szablony HTML wyposażone w specjalne markery służące do osadzania komponentów – nie korzysta z JSP • Komponenty Controller: – specyfikacja strony (XML) - wiąże markery z pozostałymi komponentami (w katalogu WEB-INF) – klasa Java implementująca interfejs org.apache.tapestry.IPage zawiera właściwości strony/modelu (w katalogu WEB-INF/classes) 441 Przykładowa aplikacja Strona formularza Strona wyników 442 Przykładowa aplikacja V specyfikacja strony V strona formularza C specyfikacja strony strona wyniku C M klasa obsługi strony wyniku klasa modelu dla strony wyniku M klasa obsługi strony formularza zintegrowana z modelem 443 Przykładowa aplikacja Kod źródłowy strony formularza <html> <body> Wyrażenie warunkowe w języku OGNL <h1>Notowania giełdowe</h1> <div jwcid="@Conditional" condition="ognl:error"> <font color="red"> <span class="error" jwcid="@Insert" value="ognl:error"> Błąd!</span> Java Web Component ID: wskazuje <br></font> wzorzec komponentu Nazwy typów komponentów wbudowanych </div> <form jwcid="@Form" listener="ognl:listeners.formSubmit"> Symbol waloru: <input jwcid="@TextField" value="ognl:symbol" size="8"/> <input type="submit" jwcid="@Submit" value="Szukaj"/> </form> </body> </html> Nazwa właściwości strony skojarzonej z polem 444 Przykładowa aplikacja Plik specyfikacji strony formularza <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE page-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"> <page-specification class="mypackage.Gielda"> <property-specification name="error" type="java.lang.String"/> <property-specification name="symbol" type="java.lang.String"/> </page-specification> Nazwa klasy obsługi strony Nazwa właściwości strony (atrybut klasy obsługi strony) 445 Przykładowa aplikacja Klasa obsługi strony formularza public abstract class Gielda extends BasePage { public abstract String getError(); public abstract void setError(String error); public abstract String getSymbol(); public abstract void setSymbol(String symbol); Metody dostępowe dla właściwości strony (abstract wygeneruje je Tapestry) public void formSubmit(IRequestCycle cycle) { String symbol = getSymbol(); if (symbol == null || symbol.trim().length() == 0) { setError("Wprowadź symbol waloru"); return; } try { <form jwcid="@Form" listener="ognl:listeners.formSubmit"> Walor quote = ...; PokazWalor pokazWalor = (PokazWalor) cycle.getPage("PokazWalor"); pokazWalor.setQuote(quote); cycle.activate(pokazWalor); Przygotowanie i skok do strony wyświetlającej wyniki } catch (Exception e) {setError("Niepoprawny kod waloru");} } 446 Przykładowa aplikacja Kod źródłowy strony wyniku <html> <body> <h1> <span jwcid="@Insert" value="ognl:quote.spolka">Walor</span> </h1> Kurs aktualny: <span jwcid="@Insert" value="ognl:quote.kurs"> kurs</span><br> Obrót (tys.zł): <span jwcid="@Insert" value="ognl:quote.obrot"> obrót</span><br> ... <br> Atrybut klasy obsługi strony wyniku <span jwcid="@PageLink" page="Gielda">Powrót do formularza</span> </body> </html> 447 Przykładowa aplikacja Plik specyfikacji strony wyniku <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE page-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"> <page-specification class="mypackage.PokazWalor"> <property-specification name="quote" type="mypackage.Walor"/> </page-specification> Klasa obsługi strony wyniku public abstract class pokazWalor extends BasePage { public abstract Walor getQuote(); public abstract void setQuote(Walor quote); } 448 Tapestry - pozostałe własności • Walidacja parametrów wywołania, zarówno po stronie serwera, jak i po stronie klienta • Internacjonalizacja • Narzędzia wspomagające programistę – Spindle - plug-in dla Eclipse (http://spindle.sourceforge.net) 449 Jakarta Turbine Jakarta Turbine Web Application Framework 450 • Szkielet aplikacji oparty o technologię serwletów Java – W pełni zgodny z J2EE – Oparty o model MVC – Rozpowszechniany na zasadach Apache Software License • Platforma do tworzenia aplikacji, a nie tylko ich uruchamiania • Zalety (wg dokumentacji): – Łatwa personalizacja stron internetowych – Łatwa kontrola dostępu do fragmentów aplikacji • Dobry wybór dla aplikacji opartych o architekturę zorientowaną na usługi – Usługi implementowane wg wzorca projektowego singleton • Jedna instancja usługi w systemie – Zbiór predefiniowanych, gotowych do użycia usług, m.in. • Zarządzanie użytkownikami i przywilejami • „File upload” • Transformacje XSLT 451 Technologie składowe Turbine • Velocity dla warstwy prezentacji – Podstawowa technologia w Turbine, ale wspierane również JSP – Velocity jest jedną z technologii szablonów dla serwletów Java – Zapewnia separację kodu Java (serwlet) od kodu HTML (szablon) • Torque do obsługi komunikacji z bazą danych – Torque powstał jako część projektu Turbine i dalej stanowi naturalny wybór, ale wspierane inne rozwiązania np. Hibernate – Torque jest technologią odwzorowania obiektowo-relacyjnego – W odróżnieniu od konkurencyjnych rozwiązań, nie korzysta z mechanizmu Java reflection – Generuje klasy Java w oparciu o opis schematu bazy danych w formie XML 452 Model MVC w Turbine • Kontroler aplikacji Turbine: serwlet TurbineServlet + Action Event Handlers • Akcje uruchamiane są w odpowiedzi na wprowadzenie przez użytkownika danych, które wymagają interakcji z modelem • Widok stanowi warstwa prezentacji oparta o Velocity lub JSP • Model 2+1 – Ulepszony (wg jego twórców) Model 2 – Kontroler i widok ściślej ze sobą związane niż w innych implementacjach MVC Środowiska do tworzenia aplikacji Turbine 453 • Typowe środowisko to Apache Maven + Maven Environment for Turbine Applications (M.E.T.A.) – Maven = „Ant na sterydach”, – Maven wykorzystuje wtyczki (plug-ins), jedną z nich jest M.E.T.A. – Maven oparty o koncepcję repozytoriów archiwów JAR • Archiwa zdalne (www.ibiblio.com & mirrors) i lokalne • Przy pierwszej kompilacji biblioteki pobierane ze zdalnego repozytorium • Konieczność ręcznego ściągnięcia bibliotek SUN-a (względy licencyjne) • Istnieje możliwość korzystania z IDE – Rozwiązanie testowane na Eclipse – Maven generuje projekt dla Eclipse! 454 Tworzenie aplikacji startowej (1/3) • Instalacja środowiska projektanckiego – Instalacja Apache Maven – Pobranie wtyczki M.E.T.A. dla narzędzia Maven • maven-turbine-plugin-1.2.jar – Biblioteki (JAR) Turbine i pomocnicze zostaną pobrane z sieci przy pierwszej kompilacji aplikacji Turbine • Weryfikacja poprawności instalacji maven -g __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0.2 Available [Plugins] / Goals =========================== ... [turbine] deploy ...................... install-libs ................ setup ....................... sql ......................... war ......................... ( NO DEFAULT GOAL ) Deploys the Application ... updates the libraries ... Setup a new Turbine web application Build the SQL files ... Generate a Turbine based Web application (war) 455 Tworzenie aplikacji startowej (2/3) • Utworzenie aplikacji startowej: – maven -Dturbine.app.name=helloworld turbine:setup • Drzewo katalogów aplikacji: Klasy Java przygotowujące Dane do prezentacji w szablonach Szablony Velocity dla stron aplikacji 456 Tworzenie aplikacji startowej (3/3) • Instalacja aplikacji na serwerze – maven turbine:deploy (powoduje wcześniejszą kompilację, co za pierwszym razem może wiązać się ze ściąganiem bibliotek z sieci) 457 Rozbudowa aplikacji - Przykład • Dodanie nowego dynamicznego ekranu do aplikacji – Klasa Java helloworld/src/java/org/apache/turbineapp/helloworld/modules/screens/witaj.java public class witaj extends VelocityScreen { public void doBuildTemplate( RunData data, Context context ) { try { context.put( "imie", "Marek" ); } catch( Exception e ) {} } } – Szablon Velocity helloworld/src/templates/screens/witaj.vm <h1>Witaj $imie !!!</h1> • Dodanie linku do nowego ekranu na stronie powitalnej helloworld/src/templates/screens/Index.vm <a href="$link.setPage( 'witaj.vm' )">Powitanie</a> 458 AppFuse 459 AppFuse • Zbiór szkieletów aplikacji J2EE opartych na różnych zestawach technologii – – – – – Struts + Spring + Hibernate JSF + Spring + Hibernate Spring + Hibernate Tapestry + Spring + Hibernate WebWork + Spring + Hibernate • Wykorzystanie AppFuse polega na pobraniu aplikacji "startowej" z http://appfuse.dev.java.net/, a następnie jej rozbudowa poprzez implementację własnego kodu • Alternatywa dla narzędzi typu "wizard" • Skrócenie czasu prototypowania • Uproszczenie kompilacji i testowania aplikacji • "Lekka" wersja: Equinox = Struts + Spring + Hibernate 460 Piątkowy wyjazd na ćwiczenia! Autokar o godz. 8:30 sprzed budynku ON PAN