Spring Framework v3
Entender las ventajas que supone el uso de Spring en un proyecto de desarrollo SW
Aprender a configurar las distintas clases Java según el patrón IOC y AOP
Conocer los fundamentos de desarrollo Web con Spring MVC
2. S
P
R
I
N
G
Objetivos
Entender las ventajas que supone el uso de
Spring en un proyecto de desarrollo SW
Aprender a configurar las distintas clases
Java según el patrón IOC y AOP
Conocer los fundamentos de desarrollo Web
con Spring MVC
2
3. S
P
R
I
N
G
Requisitos
Experiencia con el lenguaje Java
Conocimientos del Api JDBC
Se recomienda también conocimientos de
Servlets y JSP previos
Recomendables pero no requeridos
conocimientos de Struts, Hibernate y JSF
3
4. S
P
R
I
N
G
Contenido
1. Introducción al Framework
2. Inyección de Dependencias
3. Programación orientada a aspectos (AOP)
4. Uso de Spring para acceso a Bases de Datos
5. Control de Transacciones en Spring
6. Uso de Spring en la capa Web
7. Desarrollo Web con Spring MVC
8. Gestión de recursos con Spring
9. Desarrollo de pruebas con Spring
4
6. S
P
R
I
N
G
Introducción al Framework
Orígenes
Finales de 2002, comienzos de 2003
Framework para desarrollar aplicaciones
J2EE
El más empleado
http://www.springsource.org/
Spring Framework 3.2
Spring Tool Suite 3.1
6
7. S
P
R
I
N
G
Introducción al Framework
¿Por qué Spring?
Gestión de los objetos de negocio
Estructura en capas
Arquitectura consistente
Desarrollo por componentes
Válido en proyectos existentes
Idóneo para proyectos creados desde cero
Orientado a pruebas unitarias
7
8. S
P
R
I
N
G
Introducción al Framework
Contenedor de Inversión de Control
IoC
Yo no creo los objetos ni los asocio
Trabajo con JavaBeans/POJOs
Fase 1: Definición de Clases
Fase 2: Definición e inyección de Beans
8
11. S
P
R
I
N
G
Introducción al Framework
Además proporciona:
Soporte para Aspectos
Manejo de Transaccionalidad
Acceso a BBDD JDBC, Hibernate, iBatis,
JPA, etc
Manejo de Web Services, JMX, JMS,
JavaMail
Capa Web
...
11
13. S
P
R
I
N
G
Introducción al Framework
Core Spring Container
Funciones esenciales
BeanFactory
Creador y manejador de Beans
Spring Context
Fichero de configuración
Expresion Language
Acceso a Datos e Integración
ORM y DAO
13
14. S
P
R
I
N
G
Introducción al Framework
Spring AOP
Proxies
Transacciones
Instrumentation
API para monitorizar y gestionar JMX
Spring Web
MVC
Struts, JSF,...
WebFlow
14
16. S
P
R
I
N
G
Inyección de Dependencias
Desacoplamiento de clases
Menos rigidez y fragilidad
Más reutilización
No necesidad de servicios
Clases tipo Bean/POJO
Uso de Interfaces
Uso de getters y setters
16
18. S
P
R
I
N
G
Inyección de Dependencias
ApplicationContext
Implementa BeanFactory
Subclases
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
XmlWebApplicationContext
JavaConfigApplicationContext
AnnotationConfigApplicationContext
18
19. S
P
R
I
N
G
Inyección de Dependencias
Fichero de configuración XML
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/Beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/Beans
http://www.springframework.org/schema/Beans/spring-beans-3.0.xsd">
<bean id="miBean" class="curso.ejemplos.Clase">
<property name="nombre" value="Óliver"/>
</bean>
</beans>
19
20. S
P
R
I
N
G
Inyección de Dependencias
Fichero de configuración XML
4 formas de instanciación
Singleton (default)
Prototype
Atributo scope="prototype"
Factory
Atributo factory-method="métodoEstático"
Atributo factory-bean="BeanFactoría"
Lazy
Atributo lazy-init="true"
20
22. S
P
R
I
N
G
Inyección de Dependencias
Fichero de configuración XML
Ciclo de vida del Bean
Awareness
Conocimiento del entorno del Bean
Interfaces
BeanNameAware
BeanFactoryAware
ApplicationContextAware
22
23. S
P
R
I
N
G
Inyección de Dependencias
Fichero de configuración XML
Ciclo de vida del Bean
Métodos void sin argumentos
Atributos de Bean
init-method="método"
destroy-method="método"
Atributos genéricos (etiqueta Beans)
default-init-method="métodoComún"
default-destroy-method="métodoComún"
Interfaces (anteriores a específicos)
InitializingBean
DisposableBean
23
24. S
P
R
I
N
G
Inyección de Dependencias
Fichero de configuración XML
Ejemplo
<beans default-init-method="inicial" default-destroy-method="final">
<bean id="unBean" class="curso.ejemplos.UnaClase" scope="prototype"
init-method="inicializar" destroy-method="destruir">
</bean>
<bean id="otroBean" class="curso.ejemplos.OtraClase"
factory-bean="unBean" factory-method="getInstance">
</bean>
</beans>
24
25. S
P
R
I
N
G
Inyección de Dependencias
Inyección de una Dependencia
Por propiedad (setter)
Por constructor
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="otroBean" class="curso.ejemplos.OtraClase">
<property name="dataSource" ref="unBean"/>
</bean>
<bean id="otroBeanMás" class="curso.ejemplos.OtraClase">
<constructor-arg index="0" value="Óliver" />
<constructor-arg index="1" ref="unBean" />
</bean>
25
26. S
P
R
I
N
G
Inyección de Dependencias
Inyección de una Dependencia
Bean interno privado
<bean id="otroBean" class="curso.ejemplos.OtraClase">
<property name="dataSource">
<bean class="curso.ejemplos.UnaClase">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
</property>
</bean>
26
27. S
P
R
I
N
G
Inyección de Dependencias
Tipos de datos inyectables
<bean id="ejemploTipos" class="curso.ejemplos.ClaseCompleja">
<property name="bytes" value="Texto de prueba"/>
<property name="clase" value="java.lang.String"/>
<property name="fichero" value="/tmp"/>
<property name="idioma" value="en_GB"/>
<property name="patron" value="^(.*)$"/>
<property name="propiedades">
<value>
a=b
c=d
</value>
</property>
<property name="strings" value="Luis,Ana,Jessica,Pedro"/>
<property name="url" value="http://www.google.es"/>
</bean>
27
28. S
P
R
I
N
G
Inyección de Dependencias
Tipos de datos inyectables
public class ClaseCompleja{
private byte[] bytes;
private Class clase;
private File fichero;
private Locale idioma;
private Pattern patron;
private Properties propiedades;
private String[] strings;
private URL url;
...
}
28
29. S
P
R
I
N
G
Inyección de Dependencias
Acceso a los Beans
Mediante BeanFactory
Mediante ApplicationContext
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));
Clase b1 = (Clase) bf.getBean("miBean");
Clase b2 = bf.getBean("miBean", Clase.class);
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Clase b1 = (Clase) ac.getBean("miBean");
Clase b2 = ac.getBean("miBean", Clase.class);
29
30. S
P
R
I
N
G
Inyección de Dependencias
Acceso a los Beans
Método Descripción
Boolean containsBean(String BeanName) Comprobar si está definido un Bean.
Object getBean(String name) Recuperar una instancia de un Bean.
Object getBean(String name, Class
BeanClass)
Recuperar una instancia, con el casting hecho ya
a BeanClass.
Class getType(String name) Retorna el Class de un Bean.
Boolean isSingleton(String BeanName) Devuelve true si ese Bean es un singleton.
String[] getAliases(String BeanName) Devuelve los alias del Bean con ese nombre
30
32. S
P
R
I
N
G
Inyección de Dependencias
Inyección de colecciones
<bean id="coleccion" class="curso.ejemplos.Colecciones">
<property name="ciudades">
<list>
<value>Cáceres</value>
<value>Badajoz</value>
</list>
</property>
<property name="capitales">
<set>
<ref bean="BeanMerida" />
<ref bean="BeanMadrid" />
</set>
</property>
</bean>
32
33. S
P
R
I
N
G
Inyección de Dependencias
Inyección de colecciones
<bean id="coleccion" class="curso.ejemplos.Colecciones">
<property name="capitalesDeProvincia">
<map>
<entry key="Extremadura" value="Mérida" />
<entry key-ref="BeanGalicia" value-ref="BeanSantiago" />
</map>
</property>
<property name="propiedades">
<props>
<prop key="usuario">Óliver</prop>
<prop key="clave">root</prop>
</props>
</property>
</bean>
33
34. S
P
R
I
N
G
Inyección de Dependencias
Otras inyecciones
Valores nulos
Dependencias discreccionales
<bean id="dependenciaNula" class="curso.ejemplos.UnaClase">
<property name="propiedadNula"><null/></property>
</bean>
<bean id="dependenciaDiscrecional" class="curso.ejemplos.OtraClase"
depends-on="dependenciaNula">...</bean>
34
35. S
P
R
I
N
G
Inyección de Dependencias
Otras inyecciones
Namespace de propiedades "p"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/Beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/Beans
http://www.springframework.org/schema/Beans/spring-beans-3.0.xsd">
<bean id="miBean" class="curso.ejemplos.Clase"
p:nombre="Óliver" p:padre-ref="otroBean" />
</beans>
35
36. S
P
R
I
N
G
Inyección de Dependencias
Otras inyecciones
Inyección automática
Por nombre
Por tipo
<bean id="automatica" class="curso.ejemplos.UnaClase" autowire="byName">
<!-- <property name="nombre" /> -->
</bean>
<bean id="nombre" class="curso.ejemplos.OtraClase" />
<bean id="automatica" class="curso.ejemplos.UnaClase" autowire="byType">
<!-- <property name="persona" /> -->
</bean>
<bean id="otroBean" class="curso.ejemplos.Persona" />
36
37. S
P
R
I
N
G
Inyección de Dependencias
Otras inyecciones
Inyección automática
Por constructor
Por defecto
<bean id="ctor" class="curso.ejemplos.UnaClase" autowire="constructor">
<!-- <constructor-arg ref="p" /> -->
</bean>
<bean id="p" class="curso.ejemplos.Persona" />
<beans ... default-autowire="byType">
<bean id="auto" class="curso.ejemplos.UnaClase" autowire="autodetect">
<!-- <property name="persona" /> -->
</bean>
</beans>
37
39. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Nuevo en 3.0
Formato #{...}
Permite
Referenciar Beans por ID
Invocar métodos y propiedades
Operar con valores
Buscar mediante expresiones regulares
Manipular colecciones
39
40. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Referencia por ID
Referencia a propiedad
Referencia por método
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="otro" value="#{otroBean}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="nombre" value="#{otroBean.nombre}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="otro" value="#{otroBean.seleccionar()}" />
</bean>
40
41. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Acceso a métodos
Acceso seguro
Acceso a elementos estáticos
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="nombre" value="#{otroBean.nombre.toUpperCase()}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="nombre" value="#{otroBean.nombre?.toUpperCase()}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="valor" value="#{T(java.lang.Math).random()}" />
</bean>
41
42. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Operadores
Comparadores
Expresiones Regulares
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="total" value="#{(3+2) % (7*4)^2 + ' euros'}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="Bean" value="#{!(7>6) and (true) ? Bean1 : Bean2}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="valido" value="#{Bean.dni matches '[0-9]{8}[a-z]'}" />
</bean>
42
43. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Acceso a elementos de una colección
Tamaño de la colección
Filtrado
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="tamaño" value="#{lista.size()}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="elemento" value="#{lista[2]}" />
</bean>
<bean id="unBean" class="curso.ejemplos.UnaClase">
<property name="varones" value="#{lista.?[sexo eq 'H']}" />
</bean>
43
44. S
P
R
I
N
G
Inyección de Dependencias
Lenguaje de expresiones SpEL
Primer y último elemento de una colección
Proyección de una colección
Concatenación de filtros
<property name="nombres" value="#{lista.![nombre + ' ' + apellido]}" />
<property name="elemento" value="#{lista.^[sexo eq 'M']}" />
<property name="ultimo" value="#{lista.$[sexo eq 'H']}" />
<property name="varones" value="#{lista.?[sexo eq 'H'].![nombre]}" />
44
45. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
A través del XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/Beans"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/Beans
http://www.springframework.org/schema/Beans/spring-beans-3.0.xsd">
<ctx:annotation-config />
<ctx:component-scan base-package="curso.ejemplos" />
</beans>
45
46. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Sin fichero XML
AnnotationConfigApplicationContext
// A través de la clase raíz que enlaza a las demás
ApplicationContext ac = new AnnotationConfigApplicationContext(Raiz.class);
// Referenciando un paquete
ac = new AnnotatinConfigApplicationContext("curso.ejemplos");
46
47. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Beans anotados
@Component marca una clase como inyectable
Por defecto su nombre es el de la clase
@Component
public Programador implements Persona {...}
@Component
public Formador implements Persona{...}
@Component("otraPersona")
public Otra implements Persona{...}
47
48. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Beans anotados
@Autowired por tipo en setter/campo/constructor
Admite inyección de elementos de lista
@Autowired(required=false)
private Persona persona; // error
@Autowired
public void procesar(List<Persona> p){...} // inyecta siempre
@Autowired
@Qualifier("programador")
public Clase(Persona p){...} // inyecta
48
49. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Beans anotados
@Inject equivalente a @Autowired
Admite varias inyecciones con Provider
@Inject
@Named("formador")
private Persona persona; // inyecta
@Inject
private Persona programador; // inyecta siempre
@Inject
public void procesar(Provider<Persona> provider){
Persona p = provider.get(); // Obtengo la siguiente persona inyectada
}
49
50. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Beans anotados
@Resource equivalente a @Autowired
Admite inyección por nombre
@Resource(name="formador")
private Persona persona; // inyecta
@Resource
private List<Persona> fiesta; // inyecta siempre
@Resource
@Qualifier("noExiste")
public Persona otraPersona; // inyecta sólo por ser @Resource
50
51. S
P
R
I
N
G
Inyección de Dependencias
Uso de Anotaciones
Beans anotados
@Value permite inyectar expresiones SpEL
@Value("#{otroBean.nombre}")
private String nombre;
51
53. S
P
R
I
N
G
Inyección de Dependencias
Spring JavaConfig
Clase Java de configuración
Evita el fichero XML
JavaConfigApplicationContext
// Una clase concreta (admite wildcards)
ApplicationContext ctx = new JavaConfigApplicationContext(Config.class);
// Un paquete (todas las clases @Configuration)
ctx = new JavaConfigApplicationContext("curso.ejemplos");
@Configuration
public class Config{
@Bean // equivale a <bean name="unaPersona" class="Programador" />
public Persona unaPersona(){
return new Programador();
}
} 53
54. S
P
R
I
N
G
Inyección de Dependencias
Spring JavaConfig
Inyección de dependencias
@Configuration(defaultAutowire=Autowire.BY_TYPE, defaultLazy=Lazy.FALSE)
public class Config{
@Bean(initMethodName="iniciar", destroyMethodName="liberar")
public Persona unaPersona(){
return new Programador();
}
@Bean(scope=DefaultScopes.PROTOTYPE)
public Fiesta fiesta(){
Fiesta f = new Fiesta("primavera");
f.añadir(unaPersona());
}
}
54
55. S
P
R
I
N
G
Inyección de Dependencias
Spring JavaConfig
Clases anotadas
@Configuration
@AnotationDrivenConfig
public class Config{
@Bean
public Persona unaPersona(){
return new Programador();
}
}
public class Programador implements Persona{
@PostConstruct
public void inicializar(){...}
@PreDestroy
public void liberar(){...}
}
55
56. S
P
R
I
N
G
Inyección de Dependencias
Spring JavaConfig
Múltiples ficheros de configuración
@Configuration
@AnotationDrivenConfig
@Import(Config2.class)
public class Config1 extends ConfigurationSupport{
@Autowired
Config2 cfg2;
}
@Configuration
public class Config2{
}
56
58. S
P
R
I
N
G
Aspect-Oriented Programming
¿Qué es AOP?
Inyección de funcionalidad transversal
¿Cómo?
Añadir funcionalidad
Caso particular
Inyección de métodos
No es exactamente AOP pero se parece
58
59. S
P
R
I
N
G
Aspect-Oriented Programming
Inyección de Métodos
Sustituir un método por otro
Truco del tigre
Bean especial que sustituye al método
<bean id="sustituto" class="curso.ejemplos.Sustituto" />
<bean name="original" class="curso.ejemplos.Original">
<replaced-method name="real" replacer="sustituto" />
</bean>
59
60. S
P
R
I
N
G
Aspect-Oriented Programming
Inyección de Métodos
Sustituir un método por otro
¿Cómo es el Bean?
public class Sustituto implements MethodReplacer{
public Object reimplement(Object Bean, Method real, Object[] params){
return "Tachaaaaaan!!";
}
}
60
61. S
P
R
I
N
G
Aspect-Oriented Programming
Inyección de Métodos
Inyectar objetos de retorno
Métodos tipo getter
Se devuelve un Bean para un método
Útil para clases abstractas
<bean id="sustituto" class="curso.ejemplos.Persona" />
<bean name="abstracto" class="curso.ejemplos.Residencia">
<lookup-method name="getInquilino" bean="sustituto" />
</bean>
61
63. S
P
R
I
N
G
Aspect-Oriented Programming
Terminología AOP
Aspect (Aspecto)
Funcionalidad transversal
Advice
Implementación del Aspecto
¿Qué? y ¿Cuándo?
Join Points (Puntos de unión)
Dónde se puede inyectar
Pointcuts (Puntos de corte)
Asociación de Advice y Join Point(s)
Define el ¿Dónde?
63
64. S
P
R
I
N
G
Aspect-Oriented Programming
Más conceptos
Introduction
Añadir métodos a clases existentes
Target
Objeto destinatario del aspecto
Weaving (Enlazado)
Aplicar los aspectos en los puntos de unión
Proxy
Objeto resultado de enlazar target y aspecto
64
65. S
P
R
I
N
G
Aspect-Oriented Programming
Restricciones de Spring
Sólo soporta join points de método
Antes, después o en lugar de
Admite tras excepciones
Sólo enlaza en ejecución
Vs tiempo de compilación y carga (AspectJ)
Formato Proxy
65
66. S
P
R
I
N
G
Aspect-Oriented Programming
Definición de pointcuts
En 3.x se usa el formato AspectJ
// Ejecución del método hablar con cualquier número de parámetros
// con cualquier retorno y ejecutado sobre cualquier clase
"execution(* *.hablar(..))"
// Ejecución del método hablar de la clase Persona
// con cualquier número de parámetros y cualquier retorno
// e invocado desde cualquier clase del paquete curso.ejemplos
"execution(* Persona.hablar(..)) && within(curso.ejemplos.*)"
// Ejecución del método hablar de la clase Persona
// limitado al Bean con ID orador
"execution(* Persona.hablar(..)) && bean(orador)"
66
67. S
P
R
I
N
G
Aspect-Oriented Programming
Definición de pointcust
En 3.x se usa el formato AspectJ
// Ejecución de un método público
"execution(public * *(..))"
// Ejecución de cualquier método desde un paquete/subpaquete
"within(curso.ejemplos..*)"
// Ejecución de cualquier método si el proxy hereda de Superclase
"this(curso.ejemplos.Superclase)"
// Ejecución de cualquier método si el target hereda de Superclase
"target(curso.ejemplos.Superclase)"
// Ejecución de cualquier método con un parámetro y que sea serializable
"args(java.io.Serializable)"
67
68. S
P
R
I
N
G
Aspect-Oriented Programming
Definición de pointcust
En 3.x se usa el formato AspectJ
// Ejecución de cualquier método desde una clase anotada @Transactional
"@within(org.springframework.transaction.annotation.Transactional)"
// Ejecución de cualquier método si el target tiene una anotación
"@target(curso.ejemplos.Anotacion)"
// Ejecución de cualquier método con un parámetro anotado @Anotacion
"@args(curso.ejemplos.Anotacion)"
68
69. S
P
R
I
N
G
Aspect-Oriented Programming
Configuración XML
<bean id="aspecto" class="curso.ejemplos.MiAdvice" />
<aop:config>
<aop:aspect ref="aspecto">
<aop:before method="antesDe"
pointcut="execution(* *.ejecutar(..))" />
<aop:before method="otroAntesDe"
pointcut="execution(* *.ejecutar(..))" />
<aop:after-returning method="despuesDe"
pointcut="execution(* *.ejecutar(..))" />
<aop:after-throwing method="siHayUnaExcepcion"
pointcut="execution(* *.ejecutar(..))" />
</aop:aspect>
</aop:config>
<aop:config>
<aop:aspect ref="aspecto">
<aop:pointcut name="corte"
expression="execution(* *.ejecutar(..))" />
<aop:before method="otroAntesDe" pointcut-ref="corte" />
</aop:aspect>
</aop:config>
69
71. S
P
R
I
N
G
Aspect-Oriented Programming
Ejecución "en lugar de"
Método con parámetro ProceedingJoinPoint
Etiqueta <aop:around>
<aop:config>
<aop:aspect ref="aspecto">
<aop:around method="enLugarDe" pointcut-ref="corte" />
</aop:aspect>
</aop:config>
public void enLugarDe(ProceedingJoinPoint join){
try{
antesDe();
// Procedo
join.proceed();
despuesDe();
}catch(Exception e){ enCasoDeExcepcion(); }
}
71
73. S
P
R
I
N
G
Aspect-Oriented Programming
Interceptar parámetros
E inyectar argumentos a los aspectos
public class Original{
public void recibir(String mensaje){
}
}
public class AOP{
public void interceptar(String algo){
}
}
<aop:pointcut id="corte"
expression="execution(* *.recibir(String)) && args(param1)" />
<aop:before pointcut-ref="corte" method="interceptar"
arg-names="param1" />
73
75. S
P
R
I
N
G
Aspect-Oriented Programming
Introducir funcionalidad
¿Cómo lo hago?
public interface NuevaFuncionalidad{
public void nuevoMetodo(String parametro);
}
public class Implementacion implements NuevaFuncionalidad{
public void nuevoMetodo(String parametro){
}
}
<aop:aspect>
<aop:declare-parents types-matching="curso.ejemplos.Target+"
implement-interface="curso.ejemplos.NuevaFuncionalidad"
default-impl="curso.ejemplos.Implementacion" />
</aop:aspect>
75
76. S
P
R
I
N
G
Aspect-Oriented Programming
Configuración por Anotaciones
@Aspect public class Aspecto{
@Pointcut("execution(* *.ejecutar(..)))")
public void corte(){}
@Before("corte()")
public void antesDe(){...}
@AfterReturning("corte()")
public void despuesDe(){...}
@AfterThrowing("corte()")
public void siHayUnaExcepcion(){...}
}
<aop:aspectj-autoproxy />
<!-- <aop:config>
...
</aop:config> -->
76
79. S
P
R
I
N
G
Acceso a BBDD
Spring DAO
Data Access Objects
CRUD sobre un origen de datos
En Spring
Plantillas de acceso
Patrón Template Method
Con excepciones útiles genéricas
Todas son Unchecked Exceptions
79
80. S
P
R
I
N
G
Acceso a BBDD
Spring DAO
Paquete Descripción
org.springframework.jdbc
Define las clases básicas y excepciones para
trabajar con BBDD
org.springframework.jdbc.core
Contiene las clases fundamentales como
JdbcTemplate para acceso a datos
org.springframework.jdbc.core.simple
Contiene versiones simplificadas de
JdbcTemplate para trabajar con JDK5
org.springframework.jdbc.datasource
Proporciona soporte para trabajar con
datasources
org.springframework.jdbc.support
Contiene clases de soporte simplificado
como JdbcDaoSupport
org.springframework.dao
Define una jerarquía sofisticada de
excepciones sobre las de JDBC
org.springframework.dao.support Clases de soporte para trabajar con DAO
80
81. S
P
R
I
N
G
Acceso a BBDD
Plantillas y Callbacks
Parte fija y parte variable de la consulta
2 clases de acceso
XxxTemplate
XxxDaoSupport
81
82. S
P
R
I
N
G
Acceso a BBDD
Plantillas XxxTemplate
Abstraen el acceso a un origen de datos
Clase (org.springframework.*) Plantilla para...
jdbc.core.JdbcTemplate Conexión simple con JDBC
jdbc.core.simple.SimpleJdbcTemplate
Conexión con JDBC mejorada a Java 5
(autoboxing, generics, parámetros variable)
orm.hibernate.HibernateTemplate Conexión con Hibernate 2.x
orm.hibernate3.HibernateTemplate Conexión con Hibernate 3.x
orm.ibatis.SqlMapClientTemplate Conexión con iBATIS
orm.jpa.JpaTemplate Conexión con JPA
82
83. S
P
R
I
N
G
Acceso a BBDD
Clases XxxDaoSupport
Simplifican el acceso al Template
Clase (org.springframework.*) Soporte DAO para...
jdbc.core.JdbcDaoSupport Conexión simple con JDBC
jdbc.core.simple.SimpleJdbcDaoSupport Conexión con JDBC mejorada a Java 5
orm.hibernate.HibernateDaoSupport Conexión con Hibernate 2.x
orm.hibernate3.HibernateDaoSupport Conexión con Hibernate 3.x
orm.ibatis.SqlMapClientDaoSupport Conexión con iBATIS
orm.jpa.JpaDaoSupport Conexión con JPA
83
84. S
P
R
I
N
G
Acceso a BBDD
Modelo de trabajo general
Pegas: Se pierde el control del flujo y exige
comprometer la herencia
84
85. S
P
R
I
N
G
Modelo de trabajo simplificado
Ventajas: invoco directamente al template y
no comprometo la herencia
Acceso a BBDD
85
86. S
P
R
I
N
G
Acceso a BBDD
Paso 1: Configurar un DataSource
Especificar el origen de datos
URL, usuario, contraseña, etc
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="origenDeDatosParaMySql"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/test"
p:username="root"
p:password="password"/>
86
87. S
P
R
I
N
G
Acceso a BBDD
Paso 2: Implementar el Dao
correspondiente e instanciar el Bean
Inyectando el template como propiedad
<bean id="daoClientes" class="curso.ejemplos.MiDaoClientesJdbc">
<property name="template"><bean
class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate"
p:dataSource-ref="origenDeDatosParaMySql" />
</property>
</bean>
public class MiDaoClientesJdbc implements DaoClientes{
private SimpleJdbcTemplate template;
public void añadir(Cliente c){
template.update(SQL_INSERTAR, c.getNombre(), c.getEdad());
}
}
87
88. S
P
R
I
N
G
Acceso a BBDD
Paso 2a: Implementar el Dao
correspondiente e instanciar el Bean
A través del DaoSupport
<bean id="daoClientes2" class="curso.ejemplos.DaoClientesJdbc">
<!-- Debe inyectarse esta propiedad del DaoSupport -->
<property name="dataSource" ref="origenDeDatosParaMySql" />
</bean>
public class DaoClientesJdbc extends JdbcDaoSupport implements DaoClientes{
public void añadir(Cliente c){
// SQL_INSERTAR="INSERT INTO Clientes(nombre, edad) VALUES (?,?)";
Object[] args = {c.getNombre(), c.getEdad()}; // Jdbc
getJdbcTemplate().update(SQL_INSERTAR, args);
}
}
88
89. S
P
R
I
N
G
Acceso a BBDD
Paso 3: Implementar un mapper de lectura
Para las consultas tipo SELECT
Interfaz RowMapper
<bean id="daoClientes" class="curso.ejemplos.MiDaoClientesJdbc">
<property name="miMapeador">
<bean class="curso.ejemplos.Mapper" />
</property>
</bean>
public class Mapper implements RowMapper<Cliente> {
public Cliente mapRow(ResultSet rs, int rowNum){
return new Cliente(rs.getLong("id_cliente"),
rs.getString("nombre"),
rs.getInt("edad"));
}
}
89
90. S
P
R
I
N
G
Acceso a BBDD
Paso 4: Utilizar el mapper para consultas
tipo SELECT
En cualquiera de los 2 DAO
public class MiDaoClientesJdbc implements DaoClientes{
private RowMapper<Cliente> miMapeador;
public Cliente buscar(long idCliente){
// SQL_SELECT="SELECT * FROM Clientes WHERE id_cliente=?"
return template.queryForObject(SQL_SELECT, miMapeador, idCliente);
}
}
90
91. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de Hibernate
Hibernate utiliza un objeto SessionFactory
Para ejecutar consultas
Y ficheros de configuración hbm
Para los detalles de la conexión
Para los mapeos clase-tabla
Hay que instanciar un Bean SessionFactory
Hay que referenciar los ficheros hbm
91
92. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de Hibernate
Bean LocalSessionFactoryBean
<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
id="sessionFactory">
<property name="dataSource" ref="origenDeDatosParaMySql" />
<property name="mappingResources">
<list>
<value>FicheroMapeo.hbm.xml</value>
</list>
</property>
<!-- Propiedades hbm de configuración -->
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
92
93. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de Hibernate
HibernateTemplate (I)
public class DaoClientesHibernate implements DaoClientes{
private HibernateTemplate template;
public void añadir(Cliente c){
template.save(c);
}
public Cliente buscar(long idCliente){
return template.get(Cliente.class, idCliente);
}
public List<Cliente> listar(){
return template.find("FROM Cliente");
}
}
93
94. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de Hibernate
HibernateTemplate (II)
<bean id="daoClientes" class="curso.ejemplos.DaoClientesHibernate">
<property name="template" ref="hibernateTemplate" />
</bean>
<bean class="org.springframework.orm.hibernate3.HibernateTemplate"
id="hibernateTemplate" autowire="byName">
<!--<property name="sessionFactory" ref="sessionFactory" />-->
</bean>
94
95. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de JPA
JPA emerge de Hibernate, EJB2 y JDO
Utiliza un gestor de entidades
EntityManager y EntityManagerFactory
Instanciar un Bean factoría
LocalEntityManagerFactoryBean
LocalContainerEntityManagerFactoryBean
JPA utiliza un fichero de configuración dado
META-INF/persistence.xml
95
96. S
P
R
I
N
G
Acceso a BBDD
Acceso a través de JPA
Bean LocalEntityManagerFactoryBean
Fichero persistence.xml
<bean id="emf" class="org.springframework.orm.jpa.LocalEntityFactoryBean">
<property name="persistenceUnitName" value="elementoPersistido" />
</bean>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="elementoPersistido">
<class>curso.ejemplos.Cliente</class>
<class>curso.ejemplos.Pedido</class>
<properties>
<property name="toplink.jdbc.driver" value="..." />
<property name="toplink.jdbc.url" value="..." />
<property name="toplink.jdbc.user" value="..." />
<property name="toplink.jdbc.password" value="..." />
</properties>
</persistence-unit>
</persistence>
96
97. S
P
R
I
N
G
Acceso a BBDD
Acceso alternativo a través de JPA
LocalContainerEntityManagerFactoryBean
Admite un adaptador de JPA a BD
<bean class="org.springframework.orm.jpa.LocalContainerEntityFactoryBean"
id="emf">
<property name="dataSource" value="origenDeDatosParaMySql" />
<property name="jpaVendorAdapter" ref="adaptadorJPA" />
</bean>
<!-- Adaptador para Hibernate -->
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
id="adaptadorJPA">
<property name="database" value="HSQL" />
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform"
value="org.hibernate.dialect.HSQLDialect" />
</bean>
97
100. S
P
R
I
N
G
Control de Transacciones
Transacciones en Spring
No dependen de JTA (ejb sí)
Programáticas y declarativas (AOP)
Admite entornos de persistencia
Admite XA de terceros
Spring delega
En manejadores de transacciones
Específicos de plataforma
100
101. S
P
R
I
N
G
Control de Transacciones
Manejadores
Manejador (org.springframework.*) Entorno
jdbc.datasource
.DataSourceTransactionManager
Para transacciones en JDBC o iBATIS
jms.connection.JmsTransactionManager Para JMS 1.1+
orm.hibernate3
.HibernateTransactionManager
Para transacciones en Hibernate 3
orm.jpa.JpaTransactionManager Para transacciones en JPA
transaction.jta
.JtaTransactionManager
Para transacciones distribuidas (XA)
transaction.jta
.WebLogicJtaTransactionManager
Para transacciones distribuidas en WebLogic
transaction.jta
.WebSphereUowTransactionManager
Para transacciones en WebSphere
101
103. S
P
R
I
N
G
Control de Transacciones
Manejador para JDBC e iBATIS
DataSourceTransactionManager
Asociado a un origen de datos
Invoca al objeto Connection
commit()
rollback()
<bean id="tmJDBC" class="org.springframework.jdbc.datasource.
DataSourceTransactionManager">
<!-- Debe inyectarse el origen de datos -->
<property name="dataSource" ref="origenDeDatosParaMySql" />
</bean>
103
104. S
P
R
I
N
G
Control de Transacciones
Manejador para Hibernate 3
HibernateTransactionManager
Asociado a un sessionFactory
Utiliza un objeto org.hibernate.Transaction
commit()
rollback()
<bean id="tmHib" class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<!-- Debe inyectarse un sessionFactory -->
<property name="sessionFactory" ref="sessionFactory" />
</bean>
104
105. S
P
R
I
N
G
Control de Transacciones
Manejador para JPA
JpaTransactionManager
Asociado a un entityManagerFactory
Utiliza un objeto EntityManager
commit()
rollback()
<bean id="tmJpa" class="org.springframework.orm.jpa.JpaTransactionManager">
<!-- Debe inyectarse un entityManagerFactory -->
<property name="entityManagerFactory" ref="emf" />
</bean>
105
106. S
P
R
I
N
G
Control de Transacciones
Manejador para JTA
JtaTransactionManager
Asociado a un transactionManager por JNDI
Utiliza un objeto UserTransaction
commit()
rollback()
<bean id="tmJpa" class="org.springframework.transaction.jta.
JtaTransactionManager">
<!-- Debe inyectarse un transactionManager -->
<property name="transactionManagerName" value="java:/TransacManager" />
</bean>
106
107. S
P
R
I
N
G
Control de Transacciones
Transacciones Declarativas
Implementadas como POJOs con AOP
Mediante el namespace tx o anotaciones
Aplicado sobre uno/varios métodos
Atributos aplicables:
Propagation
Isolation
Rollback rules
Timeout
Read-only
org.springframework.transaction.TransactionDefinition
107
108. S
P
R
I
N
G
Control de Transacciones
Transacciones Declarativas
<!-- Las transacciones AOP son aspectos a inyectar -->
<tx:advice id="aspectoTx" transaction-manager="tm">
<tx:attributes>
<tx:method name="add*" timeout="15"
propagation="REQUIRED" isolation="READ_COMMITED" />
<tx:method name="*"
propagation="SUPPORTS" read-only="true"
rollback-for="java.lang.NumberFormatException,MiExcepcion"
no-rollback-for="java.sql.SQLException" />
</tx:attributes>
</tx:advice>
<!-- Hay que asociarlas a una configuración AOP -->
<aop:config>
<aop:advisor advice-ref="aspectoTx" pointcut="execution(* *(..))" />
</aop:config>
108
109. S
P
R
I
N
G
Control de Transacciones
Transacciones Declarativas
Formato de anotaciones
<tx:annotation-driven transaction-manager="tm" />
@Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=true)
public class Implementación implements Interfaz{
@Transactional(isolation=Isolation.READ_REPEATABLE_READ, timeout=15)
public void métodoTransaccional() {
// Código a ejecutar dentro de la transacción
}
}
109
110. S
P
R
I
N
G
Control de Transacciones
Transacciones Programáticas
Implementar código con el comportamiento
transaccional incorporado
Plantilla de transacción y clase callback
TransactionTemplate
TransactionCallback
Método doInTransaction() del callback
Ejecuta la transacción
Dispara el rollback si es necesario
Inyectar la plantilla en el Bean
110
111. S
P
R
I
N
G
Control de Transacciones
Transacciones Programáticas
public void metodoTransaccional() {
txTemplate.execute(new TransactionCallback<Void>() {
public Void doInTransaction(TransactionStatus estado) {
try {
// Código a ejecutar dentro de la transacción
}catch(RuntimeException e) {
estado.setRollbackOnly(); // Disparo el rollback
throw e;
}
return null;
}
});
}
<bean id="miBean" class="curso.ejemplos.ClaseTransaccional">
<property name="txTemplate"><bean
class="org.springframework.transaction.support.TransactionTemplate"
p:transactionManager-ref="tm" />
</bean>
111
113. S
P
R
I
N
G
Uso de Spring en la Capa Web
Diseñar y desarrollar una aplicación Web es
una tarea ardua
Los Servlets son complicados
Exigen conversión constante de tipos
Las JSP son híbridas HTML-Java
Requiere mucho tiempo
Frameworks
Struts
JSF
EJB
113
116. S
P
R
I
N
G
Uso de Spring en la Capa Web
Antes de que apareciese Spring
EJB’s
Criterios de arquitectura erróneos
No aplicaban las best-practices
Alto acoplamiento
Poca flexibilidad
Por esta razón, un grupo de desarrolladores,
decidieron crear Spring
116
117. S
P
R
I
N
G
Uso de Spring en la Capa Web
Spring Web
Construido por encima del contexto
Proporciona contexto para otros Frameworks Web
Por ej. Struts
Spring MVC
Implementación avanzada del patrón MVC
Todo lo necesarios para crear una aplicación
completa
view-resolvers
controladores
librerías de etiquetas
...
117
118. S
P
R
I
N
G
Uso de Spring en la Capa Web
Spring Webflow
Subproyecto de Spring para manejar flujos
Creación de asistentes
O procesos en varias páginas
Controlados de manera transaccional
118
119. S
P
R
I
N
G
Uso de Spring en la Capa Web
Revisión de los scopes de un Bean
singleton y prototype
Referentes al contenedor Spring
request
Creado cada refresco de página
session
Creado por cada cliente
globalSession
Para compartir Beans entre Portlets
En Servlets se convierte en session
119
120. S
P
R
I
N
G
Uso de Spring en la Capa Web
¿Cómo accedo a Beans desde Web?
Nunca mediante FileSystem!!!!
Una de dos
Mediante ClassPath (bueno)
Mediante contexto Web (mejor)
Contextos Web utilizables
WebApplicationContext
XmlWebApplicationContext
// Mediante listener
WebApplicationContext ctxWAC = WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext());
// Automático
XmlWebApplicationContext ctxXWAC = new XmlWebApplicationContext();
ctxXWAC.setServletContext(getServletContext());
ctxXWAC.refresh();
120
121. S
P
R
I
N
G
Uso de Spring en la Capa Web
¿Cómo accedo a Beans desde Web?
Mediante listener (WebApplicationContext)
Configurar el web.xml
Automático
WEB-INF/applicationContext.xml
WEB-INF/[nombreDeServlet]-servlet.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
121
123. S
P
R
I
N
G
Spring MVC
Implementación del patrón MVC
Basada en un Servlet específico
Auto-enlazado a su contexto Spring Web
Y que accede a los Beans por tipo
DispatcherServlet
123
124. S
P
R
I
N
G
Spring MVC
¿Cómo es el patrón MVC?
Vista
Páginas JSP
Lógica de presentación
Controlador
Acciones del usuario
Lógica de decisión
Modelo
Ejecutar la lógica de negocio
124
125. S
P
R
I
N
G
Spring MVC
¿Y en Spring?
request
Request
Dispatcher Controller
Model
Model
View
Template
Recibe la request
y crea modelo
Delega la
request
Delega el
renderizado
Renderiza la
respuesta
response
Handler Mapping
View Resolver
125
126. S
P
R
I
N
G
Spring MVC
¿Cómo configurarlo?
Paso 1: Declarar el DispatcherServlet
Paso 2: Crear el fichero de beans
Paso 3: Elegir cómo mapear
Paso 4: Crear un controlador
Paso 5: Elegir cómo resolver vistas
Paso 6: Crear una vista (página Web)
126
127. S
P
R
I
N
G
Spring MVC
Paso 3: Clases HandlerMapping
Nombre Descripción y Ejemplo
BeanNameUrlHandlerMapping Usa el nombre del Bean Controlador
<bean name="/inicio.htm" ... >
SimpleUrlHandlerMapping Mapea mediante propiedades
<prop key="/verClientes.htm">
ControllerClassHandlerMapping Mapea el nombre de la clase
sustituyéndolo Controller por .htm
DefaultAnnotationHandlerMapping Mapea según anotaciones a métodos
@RequestMapping
<mvc:annotation-driven/>
ControllerBeanNameHandlerMapping Usa el nombre del Bean Controlador
127
128. S
P
R
I
N
G
Spring MVC
Paso 4: Un Controlador anotado
@Controller
public class ControlPersonas{
private Servicio servicioPersonas;
@Inject
public ControlPersonas(Servicio servicioPersonas) {
this.servicioPersonas = servicioPersonas;
}
@RequestMapping({"/","/pagina"})
public String saludar(Map<String, Object> modelo) {
modelo.put("saludo", "Hola!! Esto es un controlador");
return "vista";
}
}
128
129. S
P
R
I
N
G
Spring MVC
Paso 4: Clases Controller
Nombre Descripción
AbstractController Muy sencillo, cuando se necesita poca
funcionalidad (Servlet)
AbstractCommandController Coge automáticamente parámetros de la
request y parsea sus tipos. Admite validación
AbstractFormController Ofrece soporte para forms, validación,
asociación de vistas,...
SimpleFormController Permite mostrar un formulario y procesar sus
datos según método get/post
<property name="formView" ... />
AbstractWizardFormController Permite mostrar y procesar los datos de
varios formularios
129
130. S
P
R
I
N
G
Spring MVC
Paso 4: Un Controlador avanzado
@Controller
@RequestMapping("/productos/")
public class ControlProductos {
private Servicio servicioProductos;
// Responde a la URL /productos/buscar?id=3461
@RequestMapping(value="/buscar", method="GET")
public String buscar(int id, Model modelo) {
Producto p = servicioProductos.buscar(id);
modelo.addAttribute(p); // se llamará "p" automáticamente
return "listado";
}
// Responde a la URL /productos/{producto}
@RequestMapping("/{producto}")
public String ver(@PathVariable String producto, Model modelo){
...
}
}
130
131. S
P
R
I
N
G
Spring MVC
Paso 5: Clases ViewResolver
Nombre Descripción
InternalResourceViewResolver Busca en ficheros del WAR
<property name="prefix" ... />
BeanNameViewResolver Busca un Bean que se llame como la vista y
que sea de una clases que implemente View
XmlViewResolver Utiliza un fichero XML externo
<property name="location">
<value>/WEB-INF/views.xml</value>
</property>
JasperReportsViewResolver
FreeMakerViewResolver
TilesViewResolver
VelocityViewResolver
Buscan plantillas del Framework
correspondiente
131
132. S
P
R
I
N
G
Spring MVC
Paso 6: Una Vista JSP
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="s" uri="http://www.springframework.org/tags"%>
<div>
<c:forEach var="item" items="${lista}">
<s:url value="/personas/{x}" var="una_url" >
<s:param name="x" value="${item.nombre}" />
</s:url>
<li>
<img src="/imagenes/${item.login}.jpg" />
<a href="${una_url}">${item.nombre} ${item.apellidos}"</a>
<c:out value="(${item.edad})" />
<br/>
</li>
</c:forEach>
</div>
132
133. S
P
R
I
N
G
Spring MVC
Paso 6: Clases View
Nombre Descripción
View Interfaz genérica de vista.
Parecido a un Servlet.
AbstractExcelView Genera ficheros XLS
AbstractPdfView Genera ficheros PDF
AbstractView Genera contenido XML genérico
133
134. S
P
R
I
N
G
Spring MVC
Paso 6: Una Vista JSP con formulario
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<div>
<sf:form method="POST" modelAttribute="persona">
<fieldset>
<label for="nombre_persona">Indica tu nombre: </label>
<sf:input id="nombre_persona" path="nombre" size="15" />
<sf:errors path="nombre" delimiter=", " />
<br />
<label for="edad_persona">Indica tu edad: </label>
<sf:input id="edad_persona" path="edad" size="2" />
<br/>
<label for="password">Contraseña: </label>
<sf:password id="password" showPassword="false" />
<br/>
<input type="submit" value="enviar" />
</fieldset>
</sf:form>
</div>
134
135. S
P
R
I
N
G
Spring MVC
Validación de Datos
Objeto BindingResult recibible en Controller
Anotación @Valid aplicada al Command
La validación se anota en la clase Persona
@RequestMapping(value="/formulario", method="POST")
public String procesarPersona(@Valid Persona p, BindingResult res) {
if(res.hasErrors()){
return "formulario";
}
return "pagina";
}
public class Persona {
@Size(min=3, max=20, message="el login debe tener entre 3 y 20 chars")
@Pattern(regexp="^[a-zA-Z0-9]+$", message="Sólo chars alfanuméricos")
private String nombre;
}
135
137. S
P
R
I
N
G
Gestión de Recursos con Spring
Un ApplicationContext es también un
ResourceLoader
Recursos por URL
Ficheros de propiedades
Recursos JNDI
Utilidades
137
138. S
P
R
I
N
G
Gestión de Recursos con Spring
Acceso a recursos
ApplicationContext tiene acceso directo
Admite varios prefijos
classpath:
file:
http:
Se puede inyectar a una clase
Implementando ResourceLoaderAware
// En una clase de Aplicación
Resource res = ctx.getResource("recursos/fichero.txt");
interface ResourceLoaderAware{
void setResourceLoader(ResourceLoader loader);
}
138
139. S
P
R
I
N
G
Gestión de Recursos con Spring
Ficheros de propiedades
Property Placeholder
Property Overrider
<context:property-placeholder location="classpath:/cfg/msg.properties" />
<bean id="miBean" class="curso.ejemplos.Clase" p:nombre="${propiedad}" />
<context:property-override location="classpath:/cfg/msg.properties" />
<!-- propiedades en formato miBean.nombre=valor -->
139
140. S
P
R
I
N
G
Gestión de Recursos con Spring
Internacionalización
ApplicationContext extiende la interfaz
MessageSource
Que permite consultar ficheros localizados
A través de un bean messageSource
Accede src/Mensajes_es_es.properties
<bean id="messageSource" p:basename="Mensajes"
class="org.springframework.context.support.ResourceBundleMessageSource" />
// En una clase Java
String msj = ctx.getMessage("identificador", new Object[]{1, "hola"});
<!-- En una JSP -->
<spring:message code="identificador" />
140
141. S
P
R
I
N
G
Gestión de Recursos con Spring
Recursos en MVC
Namespace mvc en Spring 3.x
Mapea automáticamente recursos que
deben traspasar el DispatcherServlet
<mvc:resources mapping="/url-trucada/**" location="/url-real/" />
141
142. S
P
R
I
N
G
Gestión de Recursos con Spring
Recursos JNDI
Ejemplo: Pool de Conexiones
Namespace jee
Realiza el lookup JNDI automáticamente
resource-ref indica si se debe buscar
como recurso del contenedor JavaEE
Prefijo java:comp/env automático
<jee:jndi-lookup
id="dataSource"
jndi-name="/jdbc/MiPoolOrigenDeDatos"
cache="false"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"
resource-ref="true" />
142
143. S
P
R
I
N
G
Gestión de Recursos con Spring
Utilidades
Namespace util
<util:properties id="propiedades">
<prop key="jdbc.url">jdbc:hsqldb:hsql://localhost/bd</prop>
<prop key="password">P2ssw0rd</prop>
</util:properties>
<util:list id="listaPersonas">
<bean class="curso.ejemplos.Persona" p:nombre="Óliver" p:edad="18" />
<bean class="curso.ejemplos.Persona" p:nombre="Paco" p:edad="33" />
</util:list>
<!– Acceso mediante #{settings['clave']} -->
<util:properties id="settings" location="classpath:settings.properties" />
143
145. S
P
R
I
N
G
Testing con Spring
Spring Test
Integración con JUnit
Acceso al BeanFactory
Ejecución directa de tests
Rollback de transacciones en BD
145
146. S
P
R
I
N
G
Testing con Spring
¿Cómo es un Test?
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/beans.xml"})
@TransacionConfiguration("transactionManager")
@Transactional
public class UnTest {
@Autowired // Por tipo
private ObjetoAProbar objeto;
@Test
public void buscar() {
System.out.println("testando...");
String valorEsperado = 100;
Resultado encontrado = objeto.buscar(100);
Assert.assertNotNull(encontrado);
Assert.assertEquals(valorEsperado, encontrado.getValor());
}
}
146
147. S
P
R
I
N
G
Testing con Spring
¿Cómo ejecutar un test?
Liberías
spring-test
junit
Entornos de testing
Run As JUnit
Run As Maven Test
147