Aplikacje internetowe tworzone z wykorzystaniem technologii J2EE muszą być najczęściej przez długi czas pielęgnowane i rozbudowywane. Szybko się jednak okazało, że rozwijanie takich aplikacji za pomocą surowych Servletów i stron JSP nie jest dobrym rozwiązaniem. Szczególnie jeśli brać pod uwagę konieczność późniejszego porządkowania kodu. Dlatego świat programistów Java radzi sobie z podobnymi problemami za pomocą tzw. wzorców projektowych.
Jednym z takich wzorców jest MVC (ang. Model View Kontroller), czyli wzorzec złożony z kilku innych prostszych wzorców. Pozwala on rozdzielić aplikację na trzy elementy w taki sposób, aby modyfikacja któregokolwiek z nich nie wpływała na działanie pozostałych. W MVC model odpowiada za procesy biznesowe aplikacji (obliczenia, działania na bazie danych itd.), widok za prezentację aplikacji (a więc między innymi za generowanie stron w HTML-u), kontroler natomiast ma za zadanie sterować wykonaniem poszczególnych elementów aplikacji.
Programiści Java mają do wyboru wiele gotowych frameworków ułatwiających pisanie aplikacji internetowych z wykorzystaniem wzorca MVC. Najpopularniejszym i sprawdzonym w bardzo wielu projektach jest framework Struts, traktowany często przez innych programistów jako referencyjna implementacja MVC. Mimo, że obecnie wybór dobrych frameworków dla Javy jest nieco większy, umiejętność wykorzystania strutsów nadal jest obowiązkowa. Należy jednak pamiętać, że do bezproblemowego posługiwania się nim niezbędna jest znajomość JSP.
Instalacja
Przed rozpoczęciem pracy z frameworkiem Struts powinieneś zainstalować środowisko JDK (Java Development Kit) oraz kontener servletów – np. Tomcata. Proces instalacji obu tych składników opisany został w artykule wprowadzającym do JSP.
Poza tymi dwoma elementami, do wygodnej pracy potrzebny będzie jeszcze Ant. Jest to program napisany w Javie, automatyzujący proces kompilacji programów w niej napisanych (chociaż nie tylko, lecz my do tego będziemy go głównie wykorzystywali).
Aby zainstalować Anta, pobierz go ze strony http://ant.apache.org/.
Następnie rozpakuj archiwum do katalogu, w którym chcesz zainstalować program. Możesz do tego użyć darmowego programu PowerArchiwer (do pobrania ze strony http://www.powerarchiwer.com) lub WinRara.
Na koniec zostało jeszcze odpowiednie ustawienie ścieżki PATH i zmiennej środowiskowej ANT_HOME (oczywiście nie możesz zapomnieć o ustawieniu odpowiednich ścieżek i zmiennych odpowiedzialnych za poprawne działanie JDK oraz kontenera servletów).
Ścieżka PATH powinna wskazywać na podkatalog bin znajdujący się w katalogu głównym Anta. Zmienna ANT_HOME natomiast powinna zawierać ścieżkę do katalogu głównego programu.
A oto po kolei sposób ustawienia obu tych parametrów w systemie Windows:
- przejdź do Panelu Sterowania,
- kliknij ikonę System,
- w oknie Właściwości Systemu kliknij zakładkę Zaawansowane,
- w polu Zmienne systemowe odszukaj zmienną Path,
- kliknij przycisk Edytuj,
- na końcu linijki znajdującej się w polu Wartość zmiennej wpisz ścieżkę do katalogu bin znajdującego się w katalogu głównym Anta,poprzedzając ją średnikiem (np. ;c:\\apache-ant-1.6.5\\bin),
- zatwierdź wprowadzone zmiany, klikając na przycisku OK.
Do poprawnego działania Anta musisz jeszcze ustawić zmienną ANT_PATH. W tym celu, w polu Zmienne systemowe, wykonaj następujące operacje:
- kliknij przycisk Nowa,
- spowoduje to otwarcie okna, w którym w polu Nazwa zmiennej wpisz ANT_HOME,
- w polu Wartość zmiennej wpisz ścieżkę do katalogu głównego, w którym znajduje się Ant (np. c:\\apache-ant-1.6.5),
- Kliknij OK, aby zatwierdzić wprowadzoną zmienną.
Oba kroki (modyfikację zmiennej Path oraz tworzenie zmiennej ANT_HOME) przedstawione zostały na rysunkach 1 oraz 2.
Od teraz po restarcie komputera będziesz mógł korzystać z Anta z linii poleceń, z dowolnego katalogu. Pozwoli ci to na wygodne kompilowanie projektów opartych o framework Struts. Zrestartuj teraz komputer i wydaj z linii poleceń komendę ant. W jej wyniku powinieneś ujrzeć informację widoczną na rysunku 3 – będzie to oznaczać, że Ant działa prawidłowo.
Aby rozpocząć przygodę z frameworkiem Struts, musisz jeszcze pobrać archiwum z plikami ze strony http://struts.apache.org. Od razu wybierz wersję archiwum zawierającą wszystkie elementy frameworka, o nazwie struts-1.3.5-all.zip. Ma ono wszystko, co niezbędne do zbudowania naszej pierwszej aplikacji, a także dokumentację i kilka przykładowych aplikacji.
Dla ułatwienia pracy programistom, twórcy strutsów zamieścili w archiwum paczki ze szkieletem aplikacji budowanych w oparciu o ich framework. Interesująca nas paczka znajduje się w katalogu apps w pliku {stala}struts-blank-1.3.5.war{/stala}.
Rozpakuj ją – powinien sobie z tym poradzić każdy program do zarządzania archiwami zip, jeśli jednak takiego nie posiadasz, możesz skorzystać z programu jar, wchodzącego w skład JDK.
Aby to zrobić, uruchom linie komend (cmd – z paska start wybierz opcję Uruchom, następnie w oknie Uruchamianie wpisz cmd i kliknij OK) i przejdź do katalogu, w którym chcesz przechowywać projekt (w naszym przypadku będzie to główny katalog na dysku) – zobacz rysunek 4:
cd/
Załóż katalog projektu:
mkdir Hello
przegraj do niego plik struts-blank-1.3.5.war:
copy {stala}c:\\struts-1.3.5-all\\apps\\struts-blank-1.3.5.war{/stala}
Przejdź do katalogu Hello:
cd Hello
a następnie rozpakuj plik struts-blank-1.3.5.war:
jar xf struts-blank-1.3.5.war
Przyjrzyj się teraz zawartości katalogu Home.
Na rysunku 5 widać całe drzewo katalogów znajdujące się w tym podkatalogu.
Zwróć uwagę na katalogi Hello/pages, w których będziesz umieszczał strony JSP oraz Hello/WEB-INF/src/java, gdzie będzie przechowywany kod w Javie. Dodatkowo w katalogu Hello/WEB-INF znajdują się pliki konfiguracyjne web.xml (podstawowy opis tego pliku znajdziesz w artykule o JSP) oraz struts-config.xml.
Zaczynamy
Czas zacząć. Na początek coś prostego, czyli klasyczne Hello World. Do dokonywania niezbędnych działań, obliczeń operacji na bazie danych itd. służy akcja (w rzeczywistości najlepiej zamknąć
te operacje w podobne klasy, działające w sposób niezależny od akcji, tak aby mogły być wykorzystywane także w innych sytuacjach).
Następnie uzyskane w ten sposób dane powinny zostać przygotowane do zaprezentowania użytkownikom. Każda klasa akcji w strutsach dziedziczy po klasie Action i posiada przynajmniej jedną metodę
– execute:
public class HelloWorldAction extends Action{
public ActionForward execute(ActionMapping mapping, ActionFormform, HttpServletRequest request, HttpServletResponse response) {
}
}
Jak widzisz, korzystamy w tym przykładzie z sześciu klas. Dwie z nich to standardowe klasy używane także przez servlety: HttpServletRequest oraz HttpServletResponse. Pozostałe cztery są klasami frameworka Struts: ActionForward, ActionMapping, ActionForm oraz oczywiście Action.
Należy pamiętać o zaimportowaniu wszystkich tych klas w pliku z budowaną akcją. Akcja HelloWorldAction będzie bardzo prosta (zapisz ją w pliku HelloWorldAction.java w katalogu {stala}c:\\Hello\\WEB-INF\\src\\java{/stala}):
package hello;
// importujemy niezbędne klasy import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class HelloWorldAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionFormform, HttpServletRequest request, HttpServletResponse response) {
return mapping.findForward(\"hello\");
}
}
Działanie naszej aplikacji ma być bardzo proste, więc i metoda execute – wywoływana automatycznie podczas uruchamiania akcji – nie jest skomplikowana i składa się tylko z jednej linii kodu. Pozwól jednak, że zajmiemy się nią za chwilkę, po utworzeniu konfiguracji naszej aplikacji. Zanim jednak do tego przystąpimy, musisz przygotować stronę JSP, pełniącą funkcję widoku:
Strona witaj świecie
Witaj Świecie!
Stronę tę zapisz w pliku HelloWorld.jsp w katalogu {stala}c:\\Hello\\pages{/stala}. Aplikacja HelloWorld jest już gotowa. Musisz ją jeszcze skonfigurować oraz skompilować. Konfiguracja aplikacji zawarta jest w pliku {stala}struts-config.xml{/stala}. Otwórz go w edytorze, a następnie odszukaj i zmodyfikuj sekcję {html}
Możesz je teraz usunąć
(pozostawiając jedynie otwierający i zamykający
znacznik {html}
dodać własną akcję:
Prawdopodobnie po przyjrzeniu się tym linijkom oraz klasie HelloWorldAction wiesz już, o co chodzi. Path definiuje nazwę, jaką użytkownik będzie wpisywał w przeglądarce, type jest nazwą klasy naszej akcji (jak widzisz, jest to nazwa klasy wraz z pakietem).
W znaczniku forward definiujesz widok, do jakiego może się odwoływać dana akcja. Tutaj występuje widok o nazwie (name) hello, znajdujący się w pliku {stala}/pages/HelloWorld.jsp{/stala}. Przyjrzyj się jeszcze nazwie akcji i klasie HelloWorldAction. Zauważ, że w metodzie execute, do widoku odwołujesz się w akcji poprzez jego nazwę:
return mapping.findForward(\"hello\");
Linia ta nakazuje strutsom wyświetlić odpowiedni widok. I to już wszytko, można przystąpić do kompilacji. Jednak, aby skompilować naszą aplikację, musimy jeszcze wprowadzić niewielkie modyfikacje do pliku {stala}c:\\Hello\\WEB-INF\\src\\build.xml{/stala}. Jest to plik wykorzystywany przez Anta podczas procesu kompilacji. Otwórz ten plik w edytorze i odszukaj w nim linie:
Zmodyfikuj wartość value tak, aby wskazywała na plik {stala}servlet-api.jar{/stala} w kontenerze aplikacji (w Tomcacie znajduje się on w katalogu common). Następnie zmodyfikuj także wartość zmiennej project. distname na hello – jest to nazwa tworzonego projektu:
Na koniec powinieneś uaktualnić nazwy plików jar. Zmodyfikuj następujące linie:
na:
Teraz wystarczy, że z poziomu linii poleceń przejdziesz do katalogu c:\\Hello\\WEB-INF\\src i wydasz polecenie ant – zobacz rysunek 6.
Pozostało już tylko skopiować plik {stala}c:\\Hello\\WEB-INF\\hello\\hello.war{/stala} do katalogu webapps Tomcata. Po uruchomieniu Tomcata rozpakuje on automatycznie archiwum war, po czym będziesz mógł przetestować swoją nową aplikację.
Witaj, Janie Kowalski
Nadszedł czas na coś bardziej złożonego. Twoja aplikacja przywita cię z imienia i nazwiska. Wystarczy, że w tym celu podasz jej te dane, wypełniając odpowiedni formularz. Zasada działania będzie następująca:
- aplikacja wyświetli formularz zawierający pola na wpisanie imienia oraz nazwiska,
- dane wprowadzone w formularzu zostaną sprawdzone,
- jeśli będą niepoprawne, zostaniesz poproszony o dokonanie korekty,
- jeśli podasz poprawne dane, program przywita cię z imienia i nazwiska.
Na początku utwórz nowy katalog na kod aplikacji, a następnie rozpakuj w nim plik struts-blank-1.3.5.war, tak jak robiłeś to przy wcześniejszym przykładzie.
Tym razem aplikacja będzie się składała z dwóch klas. Pierwsza z nich będzie odpowiadała za przechowywanie oraz sprawdzanie informacji o użytkowniku na potrzeby akcji. Klasa taka dziedziczy po klasie ActionForm i zawsze posiada przynajmniej dwie metody – validate oraz reset.
Mają one za zadanie sprawdzenie poprawności wprowadzonych danych oraz czyszczenie tych danych. Dodatkowo klasa ta musi zawierać pola z wartościami, które użytkownik wprowadza za pośrednictwem formularza. Nie możesz zapomnieć o stworzeniu dla każdego pola odpowiedniego settera oraz gettera – zgodnie z zasadą działania beanów:
package hello;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class UserInformationForm extends ActionForm {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String name) {
firstName = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String name) {
lastName = name;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
firstName = null;
lastName = null;
}
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (firstName == null || firstName.trim().equals(\"\")) {
errors.add(\"firstName\", new ActionMessage(\"userInformation.firstName.problem\"));
}
if (lastName == null || lastName.trim().equals(\"\")) {
errors.add(\"lastName\", new ActionMessage(\"userInformation.lastName.problem\"));
}
return errors;
}
}
Najważniejsze i wymagające w związku z tym szerszego wyjaśnienia metody to oczywiście reset oraz validate. Pierwsza z nich ustawia pola klasy na wartości domyślne – w tym przypadku na null. Metoda validate natomiast odpowiada za sprawdzenie poprawności danych wprowadzonych do formularza przez użytkownika aplikacji. W tym przypadku sprawdzanie poprawności jest bardzo proste.
Jeśli użytkownik wpisał cokolwiek do pól formularza, uznajemy, że podał on swoje dane. W przeciwnym razie zgłaszamy błąd (obcinamy z lewej i z prawej strony tekst z białych znaków – czyli w tym przypadku ze spacji i tabulatorów – a następnie porównujemy to, co zostało, z pustym napisem).
Jak widzisz, metoda validate zwraca obiekt klasy ActionErrors. Klasa ta jest kolekcją przechowującą informację o błędach. Każdy ewentualny błąd możesz dodać do kolekcji, korzystając z metody add:
errors.add(\"firstName\", new Action-Message(\"userInformation.firstName.problem\"));
Metoda ta przyjmuje dwa parametry: nazwę pola klasy zawierającego niepoprawną wartość oraz obiekt klasy ActionMessage z informacji o błędzie. Informacja o błędzie jest kluczem do informacji zapisanej w pliku zasobów aplikacji.
Dodajmy więc stosowne informacje do pliku {stala}\\WEB-INF\\src\\java\\MessageResources.properties{/stala}:
userInformation.firstName.problem=Podaj imie
userInformation.lastName.problem=Podaj nazwisko
Na końcu metody validate musisz zwrócić obiekt kolekcji ApplicationErrors, czy to pusty, czy zawierający informacje o błędach:
return errors:
Druga klasa tej aplikacji będzie identyczna z klasą poprzednio opisanej akcji HelloWorldAction. Zmień tylko jej nazwę na HelloAction. Gdy wszystkie klasy są już gotowe, czas na odpowiednie skonfigurowanie całości. W pliku {stala}struts-conf.xml{/stala}, w sekcji {html}
oraz konfigurację twojej nowej akcji w sekcji {html}
Jak widzisz, konfiguracja akcji różni się nieco od tej, z którą miałeś do czynienia przy omawianiu poprzedniego przykładu. Najpierw za pomocą znacznika {html}
Następnie w konfiguracji akcji ustalamy stronę JSP – {stala}userInformation.jsp{/stala} – która ma służyć do wprowadzania danych przez użytkownika. To ona będzie się pojawiała w przeglądarce w pierwszej kolejności. Następnie za pomocą parametru name łączymy naszą akcję z klasą {stala}hello.UserInformationForm{/stala}. Wykorzystujemy tu {stala}form-beana{/stala} zdefiniowanego wcześniej.
To ona będzie sprawdzała poprawność danych wprowadzonych przez użytkownika na stronie {stala}userInformation.jsp{/stala} i ona również będzie odpowiadała za wyświetlanie tej strony (z odpowiednimi informacjami o błędach) aż do czasu, gdy użytkownik wprowadzi poprawne dane, czyli takie, które zostaną zaakceptowane przez metodę validate.
Ostatnim nowym parametrem jest attribute. Dzięki niemu zmapujesz klasę ActionForm tak, aby była ona dostępna w globalnej przestrzeni, co pozwala na łatwy dostęp do jej pól z poziomu stron JSP. Przekonasz się o tym przy omawianiu strony {stala}hello.jsp{/stala}.
Gdy konfiguracja jest już gotowa, czas, abyś stworzył strony JSP: jedną z formularzem do wprowadzania imienia i nazwiska oraz drugą, wyświetlającą powitanie.
Do budowy formularza należy skorzystać ze znacznika form znajdującego się w bibliotece taglibów strutsów – biblioteka ta zostanie dołączona na początku strony. Potrzebny taglib został w naszym przykładzie powiązany z prefiksem html.
Oto strona z formularzem:
<%@ taglib uri=\"http://struts.apache.org/tags-html\" prefix=\"html\"%>
Podaj dane
Podaj swoje dane
Imie
Nazwisko
Znacznikiem form powinieneś objąć zawartość formularza, tak jak robi się to ze standardowym znacznikiem {html}