Spring MVC
Spring MVC è il sotto-framework di Spring che permetti di servirsi del Framework Spring per realizzare applicazioni web. Possiamo quindi avvantaggiarci delle peculiarità di Spring (IoC, DI, ecc...) anche nello sviluppo di web application. Ovviamente usa il pattern MVC :-)... Cos'è Spring MVC?
Una panoramica del pattern MVC in Spring MVC Model: qui spring non fa nulla e segue la sua filosofia di base. Il modello è rappresentato dai POJO, classi Java "nude e crude" (JavaBean). Controler: il grosso di Spring MVc consiste nel fornire classi di supporto per la parte controller, ossia per ricevere e processare request http provenienti da un client. Il controller deve anche reindirizzare il client sulla vista giusta. View: la parte controlloer crea viste da mostrare al client, ma la generazione della vista vera e propria è demandata al framework di visualizzazione che si è scelto di usare. Spring supporta diversi framework di "vista" per il web: Jsp, Velocity, JSF, ecc...
Tecnologie di visualizzazione Spring quindi NON fornisce una tecnologia di vista propria ma invita a scegliere quella che si preferisce. Anche qui Spring segue la sua filosofia di base di non invasività. il framework usato (Jsp, Velocity, JSF, ecc...) non è consapevole in alcun modo di essere usato da Spring (nessuno dipendenza). Tra i vari strumenti messi a disposizione da Spring per lo sviluppo web non poteva mancare come vedremo una nutrita parte dedicata al testing. Possiamo infatti emulare delle richieste http e validare con dei test il comportamento dei nostri componenti..
Il file web.xml
Come per ogni applicazione web Java il file web.xml (nella cartella WEB-INF) contiene tutte le informazioni che il web container (Tomcat nel nostro caso) andrà ad utilizzare per caricare e rendere operativa la nostra applicazione. Il punto di partenza: il file web.xml Jug4Tenda org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springConfigFiles/jug4tendaContext.xml index.jsp
Il file web.xml di Jug4Tenda Nel nostro caso la porzione più significativa del file è la seguente: Jug4Tenda org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springConfigFiles/jug4tendaContext.xml 1 Jug4Tenda *.html Jug4Tenda *.do index.jsp
Il file web.xml di Jug4Tenda 2 Jug4Tenda org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springConfigFiles/jug4tendaContext.xml 1 Nel tag specifichiamo il nome della nostra servlet (Jug4Tenda) che viene lanciata e associata alla nostra applicazione al momento dell'avvio del web container. La servlet è del tipo org.springframework.web.servlet.DispatcherServlet. Si può notare tra il tag il nome e la posizione del file di configurazione di Spring che la nostra servlet si aspetta di caricare al suo avvio. La servlet è un vero e proprio ponte tra la nostra applicazione Spring e il mondo web.
Il file web.xml di Jug4Tenda 3... Jug4Tenda *.html Jug4Tenda *.do... Continuando l'analisi del file web.xml troviamo il tag dove indichiamo quali URL verranno indirizzati alla nostra servlet Jug4Tenda: tutti gli URL terminanti con html verranno gestiti dalla servlet Jug4Tenda. Analogamente anche gli url terminanti con.do verranno getiti da Jug4Tenda NOTA: per evitare confusione è ben dire che un url terminante con html NON deve per forza riferirsi ad un corrispondente file html esistente!
Spring MVC: il “cammino” delle request Abbiamo visto come ora tutte le request indirizzate alla nostra applicazione transitano per la servlet Jug4Tenda che le reindirizerà alle varie componenti della nostra web application. Vedremo ovviamente cosa sono queste componenti che gestiscono le request e vengono configurate nel file di contesto di Spring. E' il momento di mostrare il cammino classico di una request all'interno dell'architettura di un'applicazione Spring MVC.
Primi passi standard della request 2. Come abbiamo dettogli URL terminanti con.html passano alla nostra servlet (Jug4Tenda). Dopo di che Spring MVC “passa la palla” ad un componente che implementa l'interfaccia Controller (package org.springframework.web.servlet.mvc ) e che si occuperà di gestire fisicamente la request. Il giusto controller da usare è specificato nel file di contesto xml e dipende anche dall'URL ricevuto.
Controller e file di contesto.... < bean id="ospiteController" class="org.jugancona.jug4tenda.web.controllers.OspiteController">... <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ospiteController... Nel file di contesto vediamo che la gestione degli url che terminano con Ospite.html è delegata mediante un SimpleUrlHandlerMapping al controller ospiteController.
MultiActionController La classe OspiteControlelr oltre ad implementare l'interfaccia Controller di Spring MVC discende da una classe “preconfezionata” del framework, la MultiActionController. La sua particolarità risiede nel fatto che può richiamare diversi metodi per processare la request analizzando il contenuto dell'URL. Tradotto in parole povere il controller analizza l'URL alla ricerca di un parametro param e tenta di invocare un suo metodo pubblico che come nome ha proprioil valore di param (listOspite nel nostro esempio).
MultiActionController 2 Quale parametro della request corrisponda al nome del metodo da invocare è specificato nel file di contesto. < bean id="ospiteController" class="org.jugancona.jug4tenda.web.controllers.OspiteController">... <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ospiteController <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameRe solver"> param
MultiActionController 3 Il controller deve sempre restituire un oggetto di tipo ModelAndView (che fa parte del framework) che contiene i dati restituiti dall'elaborazione della request e una vista logica che deve essere mostrata all'utente. public ModelAndView listOspite(HttpServletRequest request, HttpServletResponse response) { List elencoOspiti = ospiteManager.getOspiti(0, 100); return new ModelAndView("listOspite", "elencoOspiti", elencoOspiti); } Il metodo listOspite obbedisce alla regola appena espressa.
ModelAndView e ViewResolver public ModelAndView listOspite(HttpServletRequest request, HttpServletResponse response) { List elencoOspiti = ospiteManager.getOspiti(0, 100); return new ModelAndView("listOspite", "elencoOspiti", elencoOspiti); } Non rimane che vedere come l'oggetto ModelAndView viene tradotto in una vista concreta, nel nostro caso una pagina JSP. Ancora una volta nel file di contesto indicheremo quale sarà il componente che trasforma gli oggetti ModelAndView in pagine jsp. Tale componente si chiama appunto viewResolver.
ModelAndView e ViewResolver 2 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResol ver"> org.springframework.web.servlet.view.JstlView /WEB-INF/jsp/.jsp Il viewResolver indica che la dispatch servlet nel restituire all'utente la pagina indicata la andrà a cercare per default alla posizione /WEB- INF/jsp/. Il file fisico della vista è ottenuto prendendo il nome della vista dell'oggetto ModelAndView (listOspite) e mettendo come prefisso.jsp (/WEB-INF/jsp/listOspite.jsp).
View resolving avanzato Quello che abbiamo visto è il meccanismo standard di Spring MVC per la risoluzione delle viste. Purtroppo tutto ciò va bene per certi usi ma in alcuni casi reali è un pò limitato... Es: se non volessimo mettere tutte le pagine JSP sotto un unica cartella? Sarebbe meglio raggrupparle per sottocartele
HandlerInterceptorAdapter Per rendere la risoluzione delle viste più fessibile ci viene in soccorso la classe HandlerInterceptorAdapter. E'una classe di Spring che consente di applicare i concetti dell'AOP alla getione delle request. Possiamo intercettare la getione delle request e decidere di fare qualcosa prima o dopo che la request sia processata.
HandlerInterceptorAdapter <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <bean id="prefixViewInterceptor" class="org.jugancona.jug4tenda.web.controllers.interceptors.PrefixViewInterceptor">