Cześć.
Chciałbym Was zapytać o jedną dość laicką kwestię.
Studiuję sobie trochę jak Spring działą pod spodem i ogólnie budowanie appek pure MVC / RESTful.
Ciekawi mnie jedna kwestia. W momencie kiedy tworzymy powiedzmy apkę opartą o architekturę czysto MVC, czyli mamy:
- Model (dane),
- View (JSP lub jakieś zewnętrze biblioteki np. Thymeleaf etc.)
- Controller (tu ogarniamy dane z modelu i przesyłamy te dane wraz ze wskazanie, który widok ma być wyświetlony).
Załużmy, że używamy Spring Boota ze starterem web, który konfiguruje Nam:
- DispatcherServleta (nie musimy mapować serwletów, wkazywać root configuracji itp.)
- ViewResolvera
+ nie musimy generalnie config klasy dowozić wraz z @EnableWebMvc, @ComponentScan, @Configuration itd.
Jeśli używamy Spring Bootowej domyślnej auto-konfiguracji to odpada Nam tworzenie beanów itd.
Spring Boota ma wbudowany kontener servletów Tomcat, więc to również Nam odpada + mamy spakowane dependencje w startery.
Świetnie. Teraz załużmy, że startujemy Naszą apkę. Mamy napisane wszystkie warstwy MVC.
Nasza apka jest z automatu deployowana jako war na serwer Tomcat.
(Wiem, że Spring Boot ogarnia większość tych rzeczy sam, ale żeby zadać odpowiednie pytanie, muszę to jakoś opisać ( ͡o ͜ʖ ͡o) )
Ok, to lecimy.
- User wysyła requesta
- Nasza apka odbiera requesta, zczytuje konfigurację z web.xml lub java-based-config.class gdzie skonfigurowany jest DispatcherServlet.
- Teraz ten DispatcherServlet (innymi słowy Front Controller) tworzy tzw. WebApplicationContext container (ten kontekst rozszerza ApplicationContext) z pliku, który w XML musi wyglądać następująco "nazwaServletu-servlet.xml" np. "frontcontroller-dispacher-servlet.xml". W tym pliku konfiguracyjnym wskazujemy ścieżkę do zeskanowania, w której będziemy trzymać klasy z adnotacją @Controller. W momencie kiedy taka klasa zostanie znaleziona, to trafia do wspomnianego kontenera.
- teraz powiedzmy, że user wykonał rządanie pod adresem /test.com/hello. Ścieżka w pliku konfiguracyjnym web.xml była następująca /test.com/*, a więc ten adress łapie się w zakresie danego DispatcherServleta. Jeśli się łapie, to uderzamy do konfiguracji dispachera, czyli pliku "frontcontroller-dispatcher-servlet.xml". W tym pliku jak już wyżej wspomniałem mamy ścieżkę, która jest skanowana pod kątem klas z @Controller.
- teraz tzw. Handler Mapping znajduje pasujący controller na podstawie URL i tak jakby zwraca go z powrotem do DispatcherServletu.
- teraz tzw. Handler Adapter egzekwuje/wywołuje logikę biznesową wewnątrz controllera.
- controller woła serwis
- serwis woła warstwę DAO
- DAO łączy się z baza danych i lecimy z powrotem do góry
- DAO -> service
- service -> controller
- controller -> Handler Adapter
- Handler Adapter -> Dispatcher
- teraz na podstawie zwróconego ModelAndView (lub samego Stringa wskazującego na nazwę widoku) Dispatcher komunikuje się z tzw. ViewResolverem.
- ViewResolver znajduje po prefixie i sufixie odpowiedni View i zwraca lokację widoku do Dispatchera
- Dispatcher znając lokację docelowego widoku przesyła do niego model (dane) i następnie ten widok jest zwracany jako Response.
Czy dobrze rozumiem workflow MVC?
Natomiast moje docelowe pytanie, to jak wewnętrznie wygląda workflow dla właśnie aplikacji RESTfulowej. Nie mamy wtedy żadnych widoków, używamy właśnie @RestController, który zawiera w sobie adnotacje @Controller + @RequestBody. Dzięki temu wiemy, że taki controller zwracać ma response w postaci JSON lub XML. Klient w headerze ("Accept") wysyła info o tym, w jakiej postaci chce uzyskać odpowiedź i wtedy uruchamiany jest odpowiedni HttpMessageConverter, np. MappingJackson2HttpMessageConverter.
Okej, ale co z działaniem pod spodem. Coś musi wykrywać, do jakiego controllera uderzyć. Czy działa to na podobnej zasadzie, tylko pomijany jest po prostu widok i od strzała wysyłany jest JSON/XML?
Z góry dziękuje każdemu, któremu chciało się powyższy esej przeczytać.