Skip to content

4. Tworzenie aplikacji MVC (Model – Widok – Kontroler)

Aplikacja internetowa często ma architekturę trójwarstwową:

Image

  • warstwa [dao] zajmuje się dostępem do danych, najczęściej danych trwałych przechowywanych w bazie danych SGBD. Mogą to jednak być również dane pochodzące z czujników, sieci itp.
  • warstwa [metier] realizuje algorytmy „biznesowe” aplikacji. Warstwa ta jest niezależna od jakiegokolwiek interfejsu użytkownika. Dlatego musi ona działać zarówno z interfejsem konsolowym, jak i internetowym czy bogatym interfejsem klienckim. Musi więc dać się testować poza interfejsem internetowym, a w szczególności za pomocą interfejsu konsolowego. Jest to zazwyczaj najbardziej stabilna warstwa architektury. Nie ulega ona zmianie w przypadku zmiany interfejsu użytkownika lub sposobu uzyskiwania dostępu do danych niezbędnych do działania aplikacji.
  • warstwa [interface utilisateur], która stanowi interfejs (często graficzny), umożliwiający użytkownikowi sterowanie aplikacją i otrzymywanie od niej informacji.

Komunikacja przebiega od lewej do prawej:

  • użytkownik wysyła żądanie do warstwy [interface utilisateur]
  • żądanie to jest formatowane przez warstwę [interface utilisateur] i przekazywane do warstwy [métier]
  • jeśli w celu przetworzenia tego żądania warstwa [métier] potrzebuje danych, zwraca się o nie do warstwy [dao]
  • każda zapytana warstwa przekazuje swoją odpowiedź do warstwy po lewej stronie, aż do momentu przekazania ostatecznej odpowiedzi użytkownikowi.

Warstwy [métier] i [dao] są zazwyczaj wykorzystywane za pośrednictwem interfejsów Java. W związku z tym warstwa [métier] zna w warstwie [dao] jedynie jej interfejsy, a nie klasy je implementujące. To właśnie zapewnia wzajemną niezależność warstw: zmiana implementacji warstwy [dao] nie ma żadnego wpływu na warstwę [métier], o ile nie zmienia się definicji interfejsu warstwy [dao]. To samo dotyczy warstw [interface utilisateur] i [métier].

Architektura MVC (Model – Widok – Kontroler) znajduje się w warstwie [interface utilisateur], gdy jest to interfejs internetowy:

Image

Przetwarzanie żądania klienta przebiega zgodnie z następującymi etapami:

  1. klient wysyła żądanie do kontrolera. Kontroler ten obsługuje wszystkie żądania klientów. Stanowi on punkt wejścia do aplikacji. Jest to element „C” w modelu MVC.
  2. kontroler C przetwarza to żądanie. W tym celu może potrzebować pomocy warstwy biznesowej. Po przetworzeniu żądania klienta może ono wywołać różne odpowiedzi. Klasycznym przykładem jest:
    • strona z komunikatami o błędach, jeśli żądania nie udało się poprawnie przetworzyć
    • strona potwierdzenia w przeciwnym razie
  3. kontroler wybiera odpowiedź (= widok), która ma zostać wysłana do klienta. Wybór odpowiedzi do wysłania do klienta wymaga kilku kroków:
    • wybór obiektu, który wygeneruje odpowiedź. Nazywa się to widokiem V, czyli V z MVC. Wybór ten zależy zazwyczaj od wyniku wykonania akcji żądanej przez użytkownika.
    • dostarczenie mu danych potrzebnych do wygenerowania tej odpowiedzi. Odpowiedź ta zawiera bowiem najczęściej informacje obliczone przez kontroler. Informacje te tworzą tzw. model M widoku, czyli M z MVC.
    • Etap 3 polega zatem na wyborze widoku V oraz na skonstruowaniu niezbędnego dla niego modelu M.
  4. Kontroler C żąda wyświetlenia wybranego widoku. Najczęściej polega to na wywołaniu konkretnej metody widoku V odpowiedzialnej za wygenerowanie odpowiedzi dla klienta. W niniejszym dokumencie terminem „widok” będziemy określać zarówno obiekt generujący odpowiedź dla klienta, jak i samą tę odpowiedź. Literatura MVC nie jest jednoznaczna w tej kwestii. Gdyby to odpowiedź miała być nazywana widokiem, obiekt generujący tę odpowiedź można by nazwać generatorem widoku.
  5. Generator widoku V wykorzystuje szablon M przygotowany przez kontroler C do zainicjowania dynamicznych części odpowiedzi, którą ma wysłać do klienta.
  6. Odpowiedź jest wysyłana do klienta. Jej dokładna forma zależy od generatora widoku. Może to być strumień HTML, PDF, plik Excel itp.

Metodologia tworzenia aplikacji internetowych MVC niekoniecznie wymaga narzędzi zewnętrznych. Można zatem stworzyć aplikację internetową w Javie o architekturze MVC przy użyciu prostego JDK oraz podstawowych bibliotek do tworzenia stron internetowych. Metoda, którą można zastosować w przypadku prostych aplikacji, wygląda następująco:

  • kontrolę sprawuje pojedynczy serwlet. Jest to element C w MVC.
  • Wszystkie żądania klienta zawierają atrybut „action”, na przykład (http://.../appli?action=liste).
  • W zależności od wartości atrybutu „action” serwlet uruchamia wewnętrzną metodę typu [doAction(...)].
  • Metoda [doAction] wykonuje akcję żądaną przez użytkownika. W tym celu, w razie potrzeby, korzysta z warstwy [métier].
  • W zależności od wyniku wykonania metoda [doAction] decyduje, która strona JSP ma zostać wyświetlona. Jest to widok V modelu MVC.
  • Strona JSP zawiera elementy dynamiczne, które muszą zostać dostarczone przez serwlet. Metoda [doAction] dostarczy te elementy. Jest to model widoku, czyli M z MVC. Szablon ten jest najczęściej umieszczany w kontekście żądania (request.setAttribute("klucz", "wartość"), a rzadziej w kontekście sesji lub aplikacji. Strona JSP ma dostęp do wszystkich trzech kontekstów.
  • Metoda [doAction] powoduje wyświetlenie widoku, przekazując tok wykonania do wybranej strony JSP. W tym celu wykorzystuje instrukcję typu [getServletContext() .getRequestDispatcher(" pageJSP ").forward(request, response)].

Ten wzorzec projektowy (Design Pattern) MVC nazywany jest wzorcem „Front Controller” lub wzorcem z jednym kontrolerem. Pojedynczy serwlet obsługuje wszystkie żądania wszystkich użytkowników.

Wróćmy do architektury poprzedniej aplikacji internetowej:

Image

Architektura ta odpowiada następującej architekturze n-warstwowej:

Image

W rzeczywistości istnieje tylko jedna warstwa – warstwa interfejsu internetowego. Ogólnie rzecz biorąc, aplikacja internetowa oparta na serwletach i stronach MVC będzie miała następującą architekturę:

Image

W przypadku prostych aplikacji taka architektura jest wystarczająca. Po napisaniu kilku aplikacji tego typu można zauważyć, że serwlety z dwóch różnych aplikacji:

  1. posługują się tym samym mechanizmem określania, którą metodę [doAction] należy wykonać w celu przetworzenia akcji żądanej przez użytkownika
  2. różnią się w rzeczywistości jedynie treścią tych metod [doAction]

W takiej sytuacji pojawia się silna pokusa, by:

  • wyodrębnić przetwarzanie (1) do generycznego serwletu, który nie zna aplikacji, w której jest używany
  • przekazać przetwarzanie (2) klasom zewnętrznym, ponieważ serwlet generyczny nie wie, w jakiej aplikacji jest używany
  • powiązać akcję żądaną przez użytkownika z klasą, która ma ją przetworzyć, za pomocą pliku konfiguracyjnego

Pojawiły się narzędzia, często nazywane „frameworkami”, które zapewniają programistom powyższe udogodnienia. Najstarszym i prawdopodobnie najbardziej znanym z nich jest Struts (http://struts.apache.org/). Jakarta Struts to projekt Apache Software Foundation (www.apache.org). Framework ten opisano na stronie (http://tahe.developpez.com/java/struts/).

Pojawił się niedawno framework Spring (http://www.springframework.org/), oferujący funkcje analogiczne do Struts. Jego zastosowanie zostało opisane w kilku artykułach (http://tahe.developpez.com/java/springmvc-part1/).

Poniżej przedstawiamy przykład architektury opartej na serwletach i stronach MVC.