Projektuję prostą aplikację internetową. Jestem nowy w tej domenie internetowej. Potrzebowałem twojej porady dotyczącej wzorców projektowych, takich jak sposób podziału odpowiedzialności między serwletami, kryteria tworzenia nowego serwletu itp.
W rzeczywistości mam kilka podmiotów na mojej stronie głównej i odpowiadających każdemu z nich mamy kilka opcji, takich jak dodawanie, edycja i usuwanie. Wcześniej korzystałem z jednego serwletu na opcje, takie jak Servlet1 do dodawania encji1, Servlet2 do edycji encji1 itd., W ten sposób otrzymaliśmy dużą liczbę serwletów.
Teraz zmieniamy nasz projekt. Moje pytanie brzmi: jak dokładnie wybierasz sposób, w jaki wybierasz odpowiedzialność serwletu. Czy powinniśmy mieć jeden serwlet na jednostkę, który przetworzy wszystkie jego opcje i przekaże żądanie do warstwy usług. Czy też powinniśmy mieć jeden serwlet dla całej strony, który przetworzy żądanie całej strony, a następnie prześle go do odpowiedniej warstwy usługi? Ponadto, jeśli obiekt żądania zostanie przekazany do warstwy usługi, czy nie.
źródło
Odpowiedzi:
Trochę przyzwoita aplikacja internetowa składa się z mieszanki wzorców projektowych. Wymienię tylko te najważniejsze.
Widok modelu Model kontrolera
Podstawowy (architektoniczny) wzorzec projektowy, którego chcesz użyć, to wzorzec Model-View-Controller . Kontroler ma być reprezentowana przez aplet, który (w) bezpośrednio tworzy / używa konkretny model i widok na podstawie wniosku. Model ma być reprezentowane przez klasy JavaBeans. Jest to często podzielne w modelu biznesowym, który zawiera działania (zachowanie) i modelu danych, który zawiera dane (informacje). View ma być reprezentowane przez pliki JSP, które mają bezpośredni dostęp do ( danych ) model EL (Expression Language).
Następnie istnieją odmiany zależne od tego, jak obsługiwane są akcje i zdarzenia. Popularne to:
MVC oparty na zapytaniach (działaniach) : jest to najprostszy do wdrożenia. The ( Biznes ) model współpracuje bezpośrednio z
HttpServletRequest
iHttpServletResponse
obiekty. Musisz samodzielnie zebrać, przekonwertować i zweryfikować parametry żądania. View może być reprezentowany przez plain vanilla HTML / CSS / JS i nie utrzymania stanu całej żądań. Tak działa między innymi Spring MVC , Struts and Stripes .Komponenty MVC : trudniejsze do wdrożenia. Ale kończy się to prostszym modelem i widokiem, w którym wszystkie „surowe” API serwletów są całkowicie oderwane. Nie powinno być potrzeby samodzielnego gromadzenia, konwertowania i sprawdzania parametrów żądania. Controller robi to zadanie i ustawia zebrane, przeliczone i potwierdzone parametry żądania w Modelu . Wystarczy zdefiniować metody działania, które będą działać bezpośrednio z właściwościami modelu. View jest reprezentowany przez „składniki” w smaku taglibs JSP lub elementów XML, który z kolei generuje HTML / CSS / JS. Stan widokudla kolejnych żądań jest utrzymywany w sesji. Jest to szczególnie przydatne w przypadku konwersji, sprawdzania poprawności i zmian wartości po stronie serwera. Tak między innymi JSF , Wicket i Play! Pracuje.
Na marginesie, hobby ze stworzonym przez siebie frameworkiem MVC jest bardzo przyjemnym ćwiczeniem edukacyjnym i polecam je, dopóki przechowujesz je do celów osobistych / prywatnych. Ale kiedy przejdziesz do profesjonalizmu, zdecydowanie zaleca się wybranie istniejącego frameworka, zamiast odkrywania go na nowo. Nauka istniejących i dobrze rozwiniętych ram zajmuje o wiele mniej czasu niż samodzielne opracowanie i utrzymanie solidnych ram.
W poniższym szczegółowym wyjaśnieniu ograniczę się do MVC opartego na żądaniach, ponieważ jest to łatwiejsze do wdrożenia.
Wzorzec kontrolera przedniego ( wzór Mediatora )
Najpierw część kontrolera powinna implementować wzór kontrolera frontowego (który jest specjalistycznym rodzajem wzoru mediatora ). Powinien składać się tylko z jednego serwletu, który zapewnia scentralizowany punkt wejścia dla wszystkich żądań. Powinien utworzyć model na podstawie informacji dostępnych w żądaniu, takich jak pathinfo lub ścieżka serwletu, metoda i / lub określone parametry. Model biznesowy jest nazywany
Action
w poniższymHttpServlet
przykładzie.Wykonanie akcji powinno zwrócić jakiś identyfikator, aby zlokalizować widok. Najprościej byłoby użyć go jako nazwy pliku JSP. Map tego apletu na określonym
url-pattern
wweb.xml
, na przykład/pages/*
,*.do
albo nawet po prostu*.html
.W przypadku prefix-wzory jak na przykład
/pages/*
można było powołać się URL jak http://example.com/pages/register , http://example.com/pages/login , etc i zapewnienia/WEB-INF/register.jsp
,/WEB-INF/login.jsp
z odpowiednim GET i POST działań . Częściregister
,login
itp Następnie dostępnychrequest.getPathInfo()
, jak w powyższym przykładzie.Kiedy używasz sufiks wzorców jak
*.do
,*.html
itp, to można powołać się URL jak http://example.com/register.do , http://example.com/login.do itp i trzeba zmienić przykłady kodu w tej odpowiedzi (takżeActionFactory
), aby zamiast tego wyodrębnić częściregister
i .login
request.getServletPath()
Wzór strategii
Action
Powinny być zgodne z wzorca Strategy . Należy go zdefiniować jako typ abstrakcyjny / interfejs, który powinien wykonywać pracę na podstawie przekazanych argumentów metody abstrakcyjnej (jest to różnica w stosunku do wzorca poleceń , przy czym typ abstrakcyjny / interfejs powinien wykonywać pracę opartą na argumenty, które zostały przekazane podczas tworzenia implementacji).Możesz
Exception
bardziej sprecyzować wyjątek niestandardowy, taki jakActionException
. To tylko podstawowy przykład rozpoczęcia, reszta zależy od Ciebie.Oto przykład,
LoginAction
który (jak sama nazwa wskazuje) loguje użytkownika.User
Sama jest z kolei model danych . View jest świadoma obecnościąUser
.Wzór metody fabrycznej
ActionFactory
Powinny być zgodne z metodą wzorca fabryczne . Zasadniczo powinien zapewniać metodę kreacji, która zwraca konkretną implementację typu abstrakcyjnego / interfejsu. W takim przypadku powinien zwrócić implementacjęAction
interfejsu na podstawie informacji podanych w żądaniu. Na przykład metoda i pathinfo (pathinfo to część za kontekstem i ścieżką serwletu w adresie URL żądania, z wyłączeniem ciągu zapytania).To
actions
z kolei powinno być statyczne /Map<String, Action>
obejmujące całą aplikację, które przechowuje wszystkie znane działania. Od Ciebie zależy, jak wypełnić tę mapę. Kodowanie:Lub konfigurowalny na podstawie pliku konfiguracyjnego właściwości / XML w ścieżce klasy: (pseudo)
Lub dynamicznie w oparciu o skanowanie w ścieżce klas dla klas implementujących określony interfejs i / lub adnotację: (pseudo)
Pamiętaj, aby utworzyć „nic nie rób”
Action
w przypadku braku mapowania. Niech na przykład zwróci bezpośredniorequest.getPathInfo().substring(1)
wtedy.Inne wzory
To były dotychczas ważne wzory.
Aby przejść o krok dalej, możesz użyć wzorca Fasada, aby utworzyć
Context
klasę, która z kolei otacza obiekty żądania i odpowiedzi oraz oferuje kilka wygodnych metod delegowania do obiektów żądania i odpowiedzi iAction#execute()
zamiast tego przekazuje ten argument jako metodę. Dodaje to dodatkową warstwę abstrakcyjną, aby ukryć surowy API Servleta. Powinieneś więc zasadniczo zerowaćimport javax.servlet.*
deklaracje przy każdejAction
implementacji. W kategoriach JSF to właśnie robią klasyFacesContext
iExternalContext
. Konkretny przykład można znaleźć w tej odpowiedzi .Następnie jest wzorzec stanu dla przypadku, w którym chcesz dodać dodatkową warstwę abstrakcji, aby podzielić zadania gromadzenia parametrów żądania, konwertowania ich, sprawdzania ich poprawności, aktualizowania wartości modelu i wykonywania akcji. W kategoriach JSF to właśnie
LifeCycle
robi.Następnie jest wzorzec złożony dla przypadku, w którym chcesz utworzyć widok oparty na komponencie, który można dołączyć do modelu i którego zachowanie zależy od stanu cyklu życia opartego na żądaniach. W kategoriach JSF
UIComponent
reprezentują to.W ten sposób możesz stopniowo ewoluować w kierunku struktury opartej na komponentach.
Zobacz też:
źródło
web.xml
, możesz użyćServletContextListener
do tego. Niech fabryka go zaimplementuje (i zarejestruje jako<listener>
wweb.xml
) i wykona zadanie napełniania podczascontextInitialized()
metody.Action
implementacji w taki sam sposób, jak w przypadku zwykłych serwletów (zobacz także serwlety wiki, aby zobaczyć podstawowy przykład, który możesz dowolnie przebudować na jakiśValidator
interfejs). Ale możesz to również zrobić przed wywołaniem akcji, ale jest to bardziej skomplikowane, ponieważ wymaga znajomości reguł sprawdzania poprawności dla poszczególnych wyświetleń. JSF został pokryty przez tę ofiaręrequired="true"
,validator="customValidatorName"
itp w znaczników XHTML.W pobitym wzorze MVC serwlet jest kontrolerem „C”.
Jego głównym zadaniem jest dokonanie wstępnej oceny wniosku, a następnie przesłanie przetwarzania na podstawie wstępnej oceny do konkretnego pracownika. Jednym z obowiązków pracownika może być ustawienie niektórych ziaren warstwy prezentacji i przesłanie żądania na stronę JSP w celu renderowania HTML. Tylko z tego powodu musisz przekazać obiekt żądania do warstwy usługi.
Nie zacząłem jednak pisać
Servlet
klas surowych . Praca, którą wykonują, jest bardzo przewidywalna i pełna wiedzy, coś, co frameworku robi bardzo dobrze. Na szczęście jest wielu dostępnych, sprawdzonych w czasie kandydatów (w kolejności alfabetycznej): Apache Wicket , Java Server Faces , Spring to tylko kilka z nich.źródło
IMHO, nie ma dużej różnicy w przypadku aplikacji internetowej, jeśli spojrzeć na nią z punktu widzenia przypisania odpowiedzialności. Zachowaj jednak przejrzystość warstwy. Zachowaj wszystko na potrzeby prezentacji w warstwie prezentacji, takie jak formant i kod specyficzne dla formantów internetowych. Po prostu trzymaj swoje podmioty w warstwie biznesowej i wszystkie funkcje (takie jak dodawanie, edycja, usuwanie) itp. W warstwie biznesowej. Jednak renderowanie ich w przeglądarce do obsługi w warstwie prezentacji. W przypadku .Net wzorzec ASP.NET MVC jest bardzo dobry, jeśli chodzi o utrzymywanie oddzielonych warstw. Spójrz na wzór MVC.
źródło
Użyłem frameworka struts i bardzo łatwo się go nauczyć. Podczas korzystania z frameworku struts na każdej stronie Twojej witryny będą znajdować się następujące elementy.
1) Użyta akcja jest wywoływana przy każdym odświeżeniu strony HTML. Ta czynność powinna wypełnić dane w formularzu, gdy strona jest ładowana po raz pierwszy i obsługiwać interakcje między internetowym interfejsem użytkownika a warstwą biznesową. Jeśli używasz strony jsp do modyfikowania modyfikowalnego obiektu java, kopia obiektu java powinna być przechowywana w formie zamiast oryginału, aby oryginalne dane nie zostały zmodyfikowane, chyba że użytkownik zapisze stronę.
2) Formularz służący do przesyłania danych między działaniem a stroną jsp. Ten obiekt powinien składać się z zestawu programów pobierających i ustawiających atrybuty, które muszą być dostępne dla pliku jsp. Formularz ma również metodę sprawdzania poprawności danych przed utrwaleniem.
3) Strona jsp, która służy do renderowania końcowego HTML strony. Strona jsp to hybryda tagów HTML i specjalnych strutów używanych do uzyskiwania dostępu do danych w formularzu i manipulowania nimi. Chociaż struts pozwala użytkownikom wstawiać kod Java do plików jsp, powinieneś być bardzo ostrożny, ponieważ utrudnia to czytanie kodu. Kod Java wewnątrz plików jsp jest trudny do debugowania i nie może być testowany jednostkowo. Jeśli zauważysz, że piszesz więcej niż 4-5 linii kodu Java w pliku jsp, kod prawdopodobnie powinien zostać przeniesiony do akcji.
źródło
Doskonała odpowiedź BalusC obejmuje większość wzorców aplikacji internetowych.
Niektóre aplikacje mogą wymagać Łańcucha odpowiedzialności
Użyj case, aby użyć tego wzoru:
Gdy moduł obsługi przetwarzania żądania (polecenia) jest nieznany, a żądanie to można wysłać do wielu obiektów. Zasadniczo ustawiasz następcę na obiekt. Jeśli bieżący obiekt nie może obsłużyć żądania lub przetworzyć go częściowo i przekazać to samo żądanie do obiektu będącego następcą .
Przydatne pytania / artykuły SE:
Dlaczego miałbym używać Łańcucha Odpowiedzialności nad Dekoratorem?
Wspólne zastosowania w łańcuchu odpowiedzialności?
wzór łańcucha odpowiedzialności od Oodesign
łańcuch_odpowiedzialności z zaopatrzenia
źródło