Ejemplo básico de Spring MVC con Maven.docx

16
Ejemplo básico de Spring MVC con Maven Posted by : hop2croft | On : 10/09/2011 Category:Spring , Spring MVC Tags:GitHub , i18n , Maven , Selenium , Spring , Spring MVC En el siguiente post vamos a hablar un poco de Spring MVC . Pero antes comentar que tengo pensado hacer una serie de post (el primero es este) sobre Spring. En concreto intentaré hablar un poco de proyecto de SpringSource como Spring MVC , Spring Web Flow, Spring Security (O Auth) ó Spring Faces. Además voy a hablar un poco de desarrollo e integración continua y pruebas (Hudson / Jenkins , Sonar ,Cobertura , Selenium, Checkstyles , PMD , …). También me gustaría tratar temas de Cloud Computing , siempre como absoluto novato en la materia, analizando herramientas como Google App Engine (GAE) ó Micro Cloud Foundry . Pero para ello todavía queda …. así que empezaré con Spring MVC . Introducción a Spring MVC. Spring MVC es un proyecto de Springsource que nos permite utilizar el patrón MVC de una forma sencilla dentro de nuestras aplicaciones desarrolladas conSpring . En la siguiente imagen vemos el esquema de cómo funciona Spring MVC . Si hemos realizado previamente desarrollo web podemos identificar claramente que en Spring MVC , nuestro DispatcherServlet funciona bajo

Transcript of Ejemplo básico de Spring MVC con Maven.docx

Page 1: Ejemplo básico de Spring MVC con Maven.docx

Ejemplo básico de Spring MVC con MavenPosted by : hop2croft | On : 10/09/2011Category:Spring, Spring MVCTags:GitHub, i18n, Maven, Selenium, Spring, Spring MVC

En el siguiente post vamos a hablar un poco de Spring MVC. Pero antes comentar

que tengo pensado hacer una serie de post (el primero es este) sobre Spring. En

concreto intentaré hablar un poco de proyecto de SpringSource como Spring

MVC, Spring Web Flow, Spring Security (O Auth) ó Spring Faces. Además voy

a hablar un poco de desarrollo e integración continua y pruebas

(Hudson / Jenkins, Sonar,Cobertura, Selenium, Checkstyles, PMD, …).

También me gustaría tratar temas de Cloud Computing , siempre como absoluto

novato en la materia, analizando herramientas como Google App Engine (GAE)

ó Micro Cloud Foundry. Pero para ello todavía queda …. así que empezaré

con Spring MVC.

Introducción a Spring MVC.Spring MVC es un proyecto de Springsource que nos permite utilizar el patrón

MVC de una forma sencilla dentro de nuestras aplicaciones desarrolladas

conSpring. En la siguiente imagen vemos el esquema de cómo funciona Spring

MVC.

Si hemos realizado previamente desarrollo web podemos identificar claramente que

en Spring MVC, nuestro DispatcherServlet funciona bajo el patrón front

Page 2: Ejemplo básico de Spring MVC con Maven.docx

controller. El patrón front controller nos da un punto de entrada único a

nuestras peticiones. De manera que todas ellas van a pasar por un mismo Servlet,

en el caso de Spring MVC, se trata de DispatcherServlet. Este Servlet se va a

encargar de gestionar toda la lógica en nuestra aplicación.

El flujo básico en una aplicación bajo Spring MVC es el siguiente:

La petición llega a nuestro DispatcherServlet (1)

El DispatcherServlet tendrá que encontrar que controlador va a tratar la petición.

Para ello el DispatcherServlet tiene que encontrar el manejador asociado a la url de

la petición. Todo esto se realiza en la fase de HandlerMapping (2).

Una vez encontrado ese Controller, nuestro DispatcherServlet le dejará gestionar a

éste la petición (3). En nuestro controlador se deberá realizar todo la lógica de

negocio de nuestra aplicación, es decir, aquí llamaremos a nuestra capa de

servicios. El controlador devolverá al Dispatcher un objeto de

tipo ModelAndView (4). ¿Qué quiere decir esto? En pocas palabras Model será los

valores que obtengamos de nuestra capa de servicio y View será el nombre de la

vista en la que queremos mostrar la información que va contenida dentro de ese

Model.

Una vez pasado este objeto ModelAndView al DispatcherServlet, será éste el que

tendrá que asociar el nombre de la vista retornada por el controlador a una vista

concreta (página jsp, jsf, …). Este proceso viene indicado en la imagen

como ViewResolver (4).

Finalmente y una vez resuelta la vista, nuestro DispatcherServlet tendrá que pasar

nuestro Model (los valores recogidos en el controlador a través de nuestra capa de

servicios) a la vista concreta View (5).

En los pasos de HandlerMapping, selección de Controller y ViewResolver

podemos indicarle a nuestro DispatcherServlet qué estrategia queremos seguir. Os

dejo una entrada del blog de Alex Fuentes donde explica de manera bastante

concisa los tipos de estrategias disponibles.

Proyecto de Spring MVC con Maven¿Por qúe utilizar GitHub?.Bueno, el punto anterior era teoría, vamos a ver un proyecto donde explicar las

clases Java y los ficheros de configuración básica para empezar con Spring MVC.

Como siempre los proyectos estarán gestionados con Maven (2.2.1). Como

novedad voy a subir el código a GitHub, así quien quiera probar los ejemplos

simplemente tendrá que acceder mi repositorio público en la siguiente dirección:

[email protected]:IvanFernandez/hop2croftRepository.git

Si no conoces todavía Git, puedes empezar echando un vistazo a los siguientes

post:

Git como herramienta de control de   versiones

Arquitectura de   Git

Page 3: Ejemplo básico de Spring MVC con Maven.docx

GitHub , repositorio remoto de   Git

Las razones por la que subo el código a GitHub son varias. Por un lado creo que

facilita seguir el post tener todo el código disponible y poder probarlo por uno

mismo. Además, y personalmente no me gusta nada, cuando estoy leyendo un post

y veo que por ejemplo no están incluidos los imports en el código ó poner todo el

código de un método . Subiendo el código a GitHub se puede escribir un post sin

necesidad de poner los imports ó sólo parte de una clase (y no hacer un post

kilométrico), pero a la vez la persona que lo está leyendo no se pierde. Finalmente y

se alguien se anima con GitHub se puede hacer un fork de los distintos proyectos,

añadir funcionalidad y que esté a disposición de todos.

Explicación del código

Yendo ya al proyecto concreto y para hacer más claro una imagen general del

proyecto creo que es bueno poner una imagen con la estructura del proyecto vista

desde Eclipse.

Page 4: Ejemplo básico de Spring MVC con Maven.docx

Como podemos ver en la anterior imagen al estar creado nuestro proyecto con

Maven se ha creado la estructura típica de un proyecto Maven, es decir:

Carpeta src/main/javaAquí vamos a guardar nuestras clases Java. En concreto tenemos cuatro paquetes:

Controller. estará asociado a nuestros controladores. En nuestro caso vamos a

tener dos controladores. CarController que se ejecutará cuando se solicite la página

car.html y CarFormController que se ejecutará cuando se solicite carForm.html

Domain. nuestras clases de dominio. Vamos a utilizar una clase que modela un

coche, Car.java. Ya hemos visto en otros post los servicios para crear, modificar y

eliminar un coche (y por ende cualquier clase) en una base de datos.

Exception. en este paquete estarán las clases que tratarán las posibles

excepciones que se generen por nuestro codigo.

Interceptor. en este paquete tenemos los interceptores de Spring MVC. Los

interceptores sirven en Spring para tratar las peticiones y añadirles cierta lógica.

Page 5: Ejemplo básico de Spring MVC con Maven.docx

Services. las clases que llaman a nuestro servicio. En lugar de utilizar los servicios

implementados en otros post, por sencillez y sobre todo para no sobrecargar los

ficheros de configuración vamos a hacer que nuestros servicios no vayan contra la

base de datos. Así el servicio CarService va a devolver una lista fija indicada en la

propia clase.

Carpeta src/main/resourcesEn este paquete vamos a guardar los ficheros necesarios en nuestro proyecto.

Locale. Nuestra aplicación va a escribir sus páginas jsp en el idioma que por

defecto que venga indicado en el navegador usado. Para ello habrá una serie de

ficheros de propiedades nombrados como message*.properties. En estos ficheros

estarán declaradas una serie de cadenas de texto y su valor. Cuando la página se

pinte hará uso de estos ficheros de propiedades para escribir el texto.

Spring. En esta carpeta tendremos nuestro fichero de contexto de la

aplicación, applicationContext.xml. En este fichero simplemente vamos a cargar en

nuestro contexto la carpeta locale que acabamos de explicar.

view_es.properties. Este fichero todavía no lo vamos a utilizar. La idea es utilizar

este fichero para hacer redirecciones en nuestros navegadores.

Carpeta src/main/testDe momento sólo he creado una clase de test. Esta clase de test está realizada

usando el framework Selenium. Este test nos permite hacer pruebas de regresión,

es decir, nuestra clase de test abrirá nuestro navegador y ejecutará una secuencia

de acciones (rellenar una caja de texto, pulsar un botón, irnos de una página a otra,

…). El siguiente post que escribiré será una pequeña explicación de como empezar

con Selenium.

Carpeta src/main/webapp/WEB-INFTenemos una serie de carpetas y ficheros de configuración que vamos a explicar a

continuación:

carpeta jsp. Aquí vamos a guardar nuestras páginas jsp. Por el momento vamos a

escribir nuestra parte de vista lo más sencilla posible. Más adelante quizá se utilice

otro framework como ZKoss ó alguna de las implementaciones de JSF.

carpeta spring. Dentro de esta carpeta tenemos el fichero car-service.xml. En este

fichero lo único que vamos a hacer es crear un bean que usará la clase de servicio

CarService.

car-servlet.xml. Vamos a explicar el contenido de este fichero a continuación.Este

fichero incluirá en el contexto de nuestroDispatcherServlet una serie de beans. Lo

primero que vemos es que cargamos el fichero car-service.xml. De manera que en

el contexto de nuestro DispatcherServlet tendremos a nuestra disposición un

Page 6: Ejemplo básico de Spring MVC con Maven.docx

beanCarService.

El siguiente fragmento nos permite entre otras cosas poder acceder a

nuestro carService desde nuestros controller utilizando para ello la

anotació[email protected] <context:annotation-config />

El siguiente bean se encargará de mapear las peticiones hechas desde car.html con

el controlador implementado en la clase CarController. Para el resto de peticiones

utilizaremos el mapeo hecho directamente por la

clase ControllerClassNameHandlerMapping.

 

1 <beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">

2     <property name="caseSensitive" value="true" />

3 </bean>

Como hemos visto las vistas tienen que resolverse en un paso intermedio entre la

llamada al controlador y la generación de la vista. Para ello vamos a utilizar el

servlet InternalResourceViewResolver. Este servlet buscará las páginas con formato

jsp en la url /WEB-INF/jsp.

1 <bean

2     class="org.springframework.web.servlet.view.InternalResourceViewResolver">

3     <property name="prefix" value="/WEB-INF/jsp/"></property>

4     <property name="suffix" value=".jsp"></property>

5     <property name="order" value="1" />

6 </bean>

En la siguiente parte declaramos la parte de interceptores. Vamos a declarar un

interceptor en la clase TimeResponseInterceptor que simplemente añadirá un valor

a nuestra petición el tiempo que ha pasado desde que se inicia hasta que termina.

Este valor podrá ser más tarde usado por nuestra vista. Para usar nuestro

interceptor lo tenemos que declarar utilizando la clase

BeanNameUrlHandlerMapping para poderlo usar en nuestras peticiones.

1<bean id="timeResponseInterceptor"class="com.hopcroft.interceptor.TimeResponseInterceptor"></bean>

2 <bean

3     class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

Page 7: Ejemplo básico de Spring MVC con Maven.docx

4     <property name="interceptors">

5         <list>

6             <ref bean="timeResponseInterceptor"></ref>7         </list>8     </property>9 </bean>

Este bean lo utilizaremos para resolver las excepciones. Si salta una exception de

tipo CarException se mostrará la página indicada, en este caso carsNotAvailable.

Si se genera una excepción de java.lang se mostará la página error.jsp. Dentro de

esta página podremos acceder a la excepción usando ${exception}.

 

1 <bean   class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

2     <property name="exceptionMappings">

3         <props>

4             <propkey="com.hopcroft.exception.CarException">carsNotAvailable</prop>

5             <prop key="java.lang.Exception">error</prop>

6         </props>

7     </property>

8 </bean>

Finalmente el siguiente bean se encargará de gestionar un formulario para crear

nuevos coches. En lugar de inyectar el carService con @Autowired en la clase

CarFormController la pasaremos como referencia en nuestro bean. La vista de

formulario será carForm y la vista cuando se haga el submit será carInsertSuccess.

1 <bean id="carFormController"class="com.hopcroft.controller.CarFormController">

2     <property name="carService" ref="carService"></property>

3     <property name="formView" value="carForm"></property>

4     <property name="successView" value="carInsertSuccess"></property>5 </bean>

web.xml. Este será el fichero de despliegue de nuestra aplicación. Aquí haremos lo

siguiente:

o Cargamos el fichero de contexto de nuestra aplicación.

1 <context-param>

Page 8: Ejemplo básico de Spring MVC con Maven.docx

2     <param-name>contextConfigLocation</param-name>

3     <param-value>classpath*:spring/applicationContext.xml</param-value>

4 </context-param>

5 <listener>

6    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

7 </listener>

o Anotamos nuestro DispatcherServlet indicaremos el formato de las peticiones al

mismo.

1 <servlet>

2     <servlet-name>car</servlet-name>

3    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

4     <load-on-startup>1</load-on-startup>

5 </servlet>

6

7 <servlet-mapping>

8     <servlet-name>car</servlet-name>9     <url-pattern>*.html</url-pattern>

10 </servlet-mapping>

o  

o  

Ejecutar el proyecto

Hemos agregado el plug-in de Jetty para poder probar la aplicación sin necesidad de

tener un contenedor web aparte en nuestro equipo. Por lo tanto nos vamos a la raíz

de nuestro proyecto y ejecutamos desde consola:

 

1 mvn clean install -DskipTests

2 mvn jetty:run

Ahora tendremos que hacer una petición a las dos páginas principales que tenemos

en nuestra aplicación.

Page 9: Ejemplo básico de Spring MVC con Maven.docx

o http://localhost:9080/spring-mvc/car.html El Dispatchertransladará la petición

a nuestro controlador CarController. La lógica de nuestro CarControllerserá bastante

sencilla.1 public class CarServiceImpl implements CarService {

2     public CarServiceImpl() {

3     }

4

5     public List<Car> getCars() throws CarException {

6         List<Car> cars = initCars();

7         if ((Calendar.getInstance().getTimeInMillis() % 2) ==0) {

8             return cars;

9         } else if ((Calendar.getInstance().getTimeInMillis() % 2) == 0) {

10             throw new CarException(1L, "Car service ", newDate());

11         } else

12             throw new RuntimeException();13     }

14

15     // TODO: llamar al DAO de car.

16     private List<Car> initCars() {

17         List<Car> carList = new ArrayList<Car>();

18         Car car = new Car();

19         car.setBrand("Ferrari");

20         car.setName("F40");

21         car.setPrice(1000000L);

22

23         Car car2 = new Car();

24         car2.setBrand("Porsche");25         car2.setName("Carrera");

26         car2.setPrice(200000L);

27

28         Car car3 = new Car();29         car3.setBrand("Opel");30         car3.setName("Astra");31         car3.setPrice(18000L);

Page 10: Ejemplo básico de Spring MVC con Maven.docx

32

33         carList.add(car);

34         carList.add(car2);35         carList.add(car3);

36

37         return carList;

38     }

o

CarController solicitará una lista de coches al servicio carService. En función de a

que hora se solicite el servicio nuestroCarControllerdevolverá:

o Una lista de coches que recogerá del servicio CarService.

o

o Una excepción CarException. Como hemos visto en el anteriormente las

excepciones de este tipo tendrán su propia página jsp carsNotAvailabledonde

devolveremos la respuesta.

Page 11: Ejemplo básico de Spring MVC con Maven.docx

o

o Una excepción genérica java.lang.Exception que estará asociada a la página error

o

o http://localhost:9080/spring-mvc/carForm.html. Tendremos un formulario

generado con Spring MVC. La parte más interesante está en como podemos

asociar un objeto de dominio a un formulario para que sea Spring MVC el que te

genere automáticamente un campo porque cada atributo del objeto de

dominio, Caren nuestro caso.1 public class CarFormController extends SimpleFormController {

2

3     public CarFormController() {

4         setCommandClass(Car.class);

Page 12: Ejemplo básico de Spring MVC con Maven.docx

5         setCommandName("carInsert");

6     }

Esto es todo en este post, espero que os sea de ayuda para entender y comenzar

con Spring MVC.

Page 13: Ejemplo básico de Spring MVC con Maven.docx

MVC en Spring En el siguiente apartado voy a detallar como esta implementado el patron Model-View-Controller sobre Spring

framework.

Como la mayoria de los framework que implementan el patron MVC, Spring tiene implementado un servlet que

realiza las tareas de Front Controller, esto significa que cada uno de los request que son realizados por el

usuario, pasan a traves de este servlet. El nombre que recibe este servlet es Dispatcher Servlet. Y como

indicamos anteriormente, todos los request que son realizados por los distintos usuarios pasan por este

componente.  Como la imagen lo indica el Request llegan al Dispatcher el cual tiene la responsabilidad de

delegar a otro componente el procesamiento del request.

Para obtener el nombre del componente que recibira el request , Spring utiliza lo que se denomina el Handler

Mapping , el cual tiene la funcion de determinar cual sera el Controller que recibira el request.

El Handler Mapping como indicamos tiene el objetivo de

indicar al dispatcher

cual sera el componente que debe recibir el request

enviado por el usuario.

Por lo cual el Dispatcher Servlet , le pregunta a uno o

mas Handler Mapping

cual sera le Controller que recivira el Request.

Dentro del Spring existe varios Handler Mapping los cuales tiene distintas

capacidades de poder mapear a los controladores.

En el siguiente cuadro se indican los Handler Mapping que posee Spring.

 Handler Mapping Como mapea el Request

 BeanNameUrlHandlerMapping Mapea controladores a URL basandose

en el nombre del Bean

 SimpleUrlHandlerMapping  Mapea controladores a URL basandose

Page 14: Ejemplo básico de Spring MVC con Maven.docx

en una collecion de propiedades que se

definen en el Spring application

context.

 ControllerClassNameHandlerMapping Mapea controladores a URL utilizando

el Controller Class Name

CommonsPathMapHandlerMapping Mapea controladores a URL usando

metadatas en el codigo del controlador.

Esta metadata es definida usando

Jakarta Commons Atributes.

Luego de que el Handler Mapping le entrega nombre del Controller que se hara cargo del Request , el

Distpacher Servlet le envia el

request al Controller.Para poder implementar un Controller sobre Spring es necesario que se cree una clase que

herede de los Controller que han sido implementados por Spring, los cuales dependiendo de la funcionalidad a

realizar es el Controller que se debera utilizar. En el siguiente cuadro se puede ver que tipos de Controller estan

disponibles sobre Spring.

 Controller type  Classes  Usarlo  cuando ...

 View

 ParameterizableViewContr

oller

UrlFilenameViewController

 Para cuando un

controlador solo

necesita desplegar

información

 Simple Controller (interface)

AbstractController

 Para controladores

simples que solo se

utilizan como Simples

Servlet

 Throwaway  ThrowawayController

 Para manejar los

request como un

Comando

Multiaction MultiActionController Para implementar una

serie de acciones con

similar lógica

Command BaseCommandController

AbstractCommandControlle

r

Si tus controladores

reciben parámetros

estos son manejados

dentro de un objeto

Form AbstractFormController

SimpleFormController

Para desplegar y

procesar un formulario,

bajo el mismo

componente

Wizard AbstractWizardFormControl

ler

Para realizar una

interacción más rica

Page 15: Ejemplo básico de Spring MVC con Maven.docx

con el usuario a través

de varias pantallas

Luego que el Controller recibe el Request , se construye un Objeto que se denomina ModelAndView ,este

componente tiene como funcion la de :1- Entregar un nombre logica a la vista que debera realizar el despliegue del Model2- Entregar un nombre logico al Model que esta asociado a este componente3- Inyectar el objeto Model el cual tiene los datos que seran desplegados en la Vista.Luego que el objeto ModelAndView es regresado al dispatcher y este componente delega la responsabilidad de la mapping del nombre logico de la vista, con el componente a utilizar al ViewResolver.El ViewResolver es el encargado de realizar el mapping entre el nombre logico de la vista y el componente. En el siguiente cuadro se indican los ViewResolver disponibles a ser configurados sobre Spring.

 View Resolver Como trabaja....

 InternalResourceViewReso

lver Resuelve el nombre logico utilizando el mapping a velocity y JSP

 BeanNameViewResolver  Resuleve el nombre logico utilizando Bean definidos en el Spring Context

ResourceBundleViewResolv

er

Define el mapping entre los nombres logicos y las vistas asociadas , definiendolo en

un archivo de propiedades

XmlViewResolver Define el mapping entre los nombres logicos y las vistas asociadas , definiendolo en

un archivo XML