Documentación originalSegunda parteTercera parteTabla de contenido:
1. Integración de Thymeleaf con Spring
2. Dialecto SpringStandard
3. Vistas y resoluciones de vista
3.1 Vistas y resoluciones de vista en Spring MVC
3.2 Vistas y resoluciones de vista en Thymeleaf
4. Administrador de inicio de Spring Thyme Seed
4.1 Concepto
4.2 Capa empresarial
4.3 Configuración de Spring MVC
4.4 Controlador
4.5 Configuración del servicio de conversión
5 Mostrar datos de inicio de semillas
6 Crear formularios
6.1 Procesando un objeto de comando
6.2 Entradas
6.3 Campos de casilla de verificación
6.4 Campos del botón de radio
6.5 Lista desplegable / Selectores de lista
6.6 Campos dinámicos
7 Verificación y mensajes de error
7.1 Errores de campo
7.2 Todos los errores
7.3 Errores globales
7.4 Mostrar errores fuera de los formularios
7.5 Objetos de error enriquecidos
8 ¡Esto sigue siendo un prototipo!
9 El servicio de conversión
9.1 Configuración
9.2 Sintaxis de doble paréntesis
9.3 Uso en formularios
9.4 # objeto de conversión de conversiones
10 Fragmentos de representación de la plantilla Fragmentos de plantilla (AJAX, etc.)
10.1 Definición de fragmentos en un bean View
10.2 Definición de fragmentos en el valor de retorno del controlador
11 características de integración avanzada
11.1 Integración con RequestDataValueProcessor
11.1 Creación de URI para controladores
12 Integración Spring WebFlow
12.2 Fragmentos de AJAX en Spring WebFlow
Esta guía explica cómo
Thymeleaf se puede integrar con Spring Framework, especialmente (pero no limitado a) Spring MVC.
Tenga en cuenta que Thymeleaf tiene integraciones para las versiones 3.xy 4.x de Spring Framework y superiores, proporcionadas por dos bibliotecas separadas llamadas thymeleaf-spring3 y thymeleaf-spring4. Estas bibliotecas se empaquetan en archivos .jar separados (thymeleaf-spring3- {versión} .jar y thymeleaf-spring4- {versión} .jar) y deben agregarse a su ruta de clase para usar las integraciones de Thymeleaf Spring en su aplicación.
Los ejemplos de código y las aplicaciones de ejemplo en esta guía usan Spring 4.xy sus integraciones Thymeleaf correspondientes, pero el contenido de este texto también se aplica a Spring 3.x. Si su aplicación usa Spring 3.x, todo lo que tiene que hacer es reemplazar el paquete org.thymeleaf.spring4 con org.thymeleaf.spring3 en los ejemplos de código.
1. Integración de Thymeleaf con Spring
Thymeleaf ofrece un conjunto de integraciones de Spring que permiten su uso como un reemplazo JSP completamente funcional en aplicaciones Spring MVC.
Estas integraciones le permitirán:
- Realice un mapeo a los métodos en sus objetos Spring MVC Controller de patrones controlados por Thymeleaf, tal como lo hace con JSP.
- Use Spring Expression Language (Spring EL) en lugar de OGNL en sus plantillas.
- Cree formularios en sus plantillas que estén completamente integrados con sus componentes de soporte de formularios y enlaces de resultados, incluido el uso de editores de propiedades, servicios de conversión y manejo de errores de validación.
- Visualice mensajes de internacionalización de archivos de mensajes administrados por Spring (a través de objetos regulares de MessageSource).
- Encuentre sus patrones utilizando mecanismos nativos de resolución de recursos de Spring.
Tenga en cuenta que para comprender completamente este tutorial, primero debe pasar por el
tutorial "
Uso de Thymeleaf ", que explica en detalle el dialecto estándar.
2. Dialecto SpringStandard
Para lograr una integración más fácil y mejor, Thymeleaf proporciona un dialecto que implementa específicamente todas las funciones necesarias para trabajar correctamente con Spring.
Este dialecto en particular se basa en el dialecto Thymeleaf estándar y se implementa en la clase org.thymeleaf.spring4.dialect.SpringStandardDialect, que en realidad deriva de org.thymeleaf.standard.StandardDialect.
Además de todas las funciones que ya están presentes en el dialecto estándar y, por lo tanto, heredadas, SpringStandard Dialect ofrece las siguientes funciones específicas:
- Usando Spring Expression Language (Spring EL o SpEL) como un lenguaje de expresión variable, no OGNL. Por lo tanto, todas las expresiones $ {...} y * {...} serán evaluadas por el motor de lenguaje de expresiones Spring. También tenga en cuenta que el soporte del compilador Spring EL (Spring 4.2.4+) está disponible.
- Acceda a cualquier componente en el contexto de su aplicación utilizando la sintaxis SpringEL: $ {@ myBean.doSomething ()}
- Nuevos atributos para procesar el formulario: th: campo , th: errores y th: errorclass , a excepción de la nueva implementación de th: object , que le permite usarlo para seleccionar el comando del formulario.
- El método de objeto y expresión es # themes.code (...) , que es equivalente a la etiqueta personalizada JSP spring: theme .
- El método de objeto y expresión, # mvc.uri (...) , que es equivalente a la función de usuario de primavera JSP : mvcUrl (...) (solo en Spring 4.1+).
Tenga en cuenta que en la mayoría de los casos, no debe usar este dialecto directamente en un objeto TemplateEngine normal como parte de su configuración. Si no tiene necesidades especiales de integración con Spring, debería crear una instancia de una nueva clase de plantilla que realice automáticamente todos los pasos de configuración necesarios:
org.thymeleaf.spring4.SpringTemplateEngine .
Ejemplo de configuración de frijol:
@Bean public SpringResourceTemplateResolver templateResolver(){
O usando la configuración Spring basada en XML:
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix" value=".html" /> <property name="templateMode" value="HTML" /> <property name="cacheable" value="true" /> </bean> <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver" /> <property name="enableSpringELCompiler" value="true" /> </bean>
3. Vistas y resoluciones de vista
3.1 Vistas y resoluciones de vista en Spring MVC
Spring MVC tiene dos interfaces que corresponden al núcleo de su sistema de plantillas:
- org.springframework.web.servlet.View
- org.springframework.web.servlet.ViewResolver
Visualiza páginas de modelos en nuestras aplicaciones y le permite cambiar y predeterminar su comportamiento definiéndolos como componentes de bean. Las vistas son responsables de representar la interfaz HTML real, como regla, de ejecutar algún tipo de motor de plantillas, por ejemplo Thymeleaf.
ViewResolvers son objetos que son responsables de obtener objetos
View para una operación y localización específicas. Por lo general, los controladores solicitan a ViewResolvers que reenvíen la vista con un nombre específico (la cadena devuelta por el método del controlador), y luego todos los medios para resolver la vista en la aplicación se ejecutan en una cadena ordenada hasta que uno de ellos pueda resolver esta vista, en cuyo caso se devuelve el objeto Vista y se le transfiere el control. para renderizar HTML.
Tenga en cuenta que no todas las páginas de nuestras aplicaciones deben definirse como vistas, sino solo aquellas cuyo comportamiento queramos no sea estándar o personalizado de una manera especial (por ejemplo, al conectarle algunos componentes especiales). Si se solicita un ViewResolver para una vista que no tiene un bean correspondiente (que es un caso común), se crea una nueva Vista ad hoc y se devuelve.Una
configuración típica de
JSP + JSTL ViewResolver en una aplicación Spring MVC del pasado se veía así:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsps/" /> <property name="suffix" value=".jsp" /> <property name="order" value="2" /> <property name="viewNames" value="*jsp" /> </bean>
Un vistazo rápido a sus propiedades es suficiente para descubrir cómo se configuró:
- viewClass establece la clase de instancias de vista. Esto es necesario para el reconocedor JSP, pero para nada cuando estamos trabajando con Thymeleaf.
- El prefijo y el sufijo funcionan de manera similar a los atributos con el mismo nombre en los objetos Thymeleaf TemplateResolver.
- order establece el orden en el que se solicitará ViewResolver en la cadena.
- viewNames le permite definir (con comodines) los nombres de las vistas que resolverá este ViewResolver.
3.2 Vistas y resoluciones de vista en Thymeleaf
Thymeleaf ofrece implementaciones para las dos interfaces mencionadas anteriormente:
- org.thymeleaf.spring4.view.ThymeleafView
- org.thymeleaf.spring4.view.ThymeleafViewResolver
Estas dos clases serán responsables de manejar las plantillas Thymeleaf como resultado de la ejecución de los controladores.
La configuración de Resolver Thymeleaf View es muy similar a la JSP:
@Bean public ThymeleafViewResolver viewResolver(){ ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine());
... o en XML:
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine" /> <property name="order" value="1" /> <property name="viewNames" value="*.html,*.xhtml" /> </bean>
El parámetro
templateEngine , por supuesto, es el objeto SpringTemplateEngine que definimos en el capítulo anterior. Los otros dos (
order y
viewNames ) son opcionales y tienen el mismo significado que en JSP ViewResolver, que vimos anteriormente.
Tenga en cuenta que no necesitamos parámetros de prefijos o sufijos, porque ya están especificados en Template Resolver (que, a su vez, se pasa a Template Engine).
Pero, ¿qué sucede si queremos definir un
bean View y
agregarle algunas variables estáticas ? Fácil, solo defina un prototipo para ello:
@Bean @Scope("prototype") public ThymeleafView mainView() { ThymeleafView view = new ThymeleafView("main");
Una vez hecho esto, puede solicitar este componente seleccionándolo por su nombre (en este caso mainView).
4. Administrador de inicio de Spring Thyme Seed
El código fuente de los ejemplos que se muestran en este y en los capítulos siguientes de esta guía se puede encontrar en el repositorio de
GitHub Spring Seyme Seed Starter Manager .
4.1 Concepto
Con respecto a Thymeleaf, somos grandes admiradores del tomillo, y cada primavera preparamos nuestros kits de inicio con buena tierra y nuestras semillas favoritas, los plantamos bajo el sol español y esperamos pacientemente a que crezcan nuestras nuevas plantas.
Pero este año, estábamos cansados de pegar etiquetas en los contenedores de semillas iniciales para averiguar qué semillas había en cada celda del contenedor, por lo que decidimos preparar la aplicación usando Spring MVC y
Thymeleaf para ayudarnos a catalogar nuestros iniciadores:
Spring Thyme SeedStarter Manager .

Similar a la aplicación Good Thymes Virtual Grocery que desarrollamos en el tutorial Usando Thymeleaf, STSM nos permite demostrar los aspectos más importantes de la integración de Thymeleaf como un motor de plantillas para Spring MVC.
4.2 Capa empresarial
Necesitaremos una capa empresarial muy simple para nuestra aplicación. En primer lugar, veamos nuestros objetos modelo:

Un par de clases de servicio muy simples proporcionarán los métodos comerciales necesarios. Como:
@Service public class SeedStarterService { @Autowired private SeedStarterRepository seedstarterRepository; public List<SeedStarter> findAll() { return this.seedstarterRepository.findAll(); } public void add(final SeedStarter seedStarter) { this.seedstarterRepository.add(seedStarter); } }
Y:
@Service public class VarietyService { @Autowired private VarietyRepository varietyRepository; public List<Variety> findAll() { return this.varietyRepository.findAll(); } public Variety findById(final Integer id) { return this.varietyRepository.findById(id); } }
4.3 Configuración de Spring MVC
A continuación, debemos
configurar la configuración de Spring MVC para la aplicación, que incluirá no solo artefactos estándar de Spring MVC, como el procesamiento de recursos o anotaciones de escaneo, sino también crear instancias de
Template Engine y
View Resolver .
@Configuration @EnableWebMvc @ComponentScan public class SpringWebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { private ApplicationContext applicationContext; public SpringWebConfig() { super(); } public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("/images/**").addResourceLocations("/images/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); } @Bean public ResourceBundleMessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("Messages"); return messageSource; } @Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); } @Bean public SpringResourceTemplateResolver templateResolver(){
4.4 Controlador
Por supuesto, también necesitamos un controlador para nuestra aplicación. Dado que STSM contendrá solo una página web con una lista de valores iniciales y un formulario para agregar nuevos, escribiremos solo una clase de controlador para todas las interacciones del servidor:
@Controller public class SeedStarterMngController { @Autowired private VarietyService varietyService; @Autowired private SeedStarterService seedStarterService; ... }
Ahora veamos qué podemos agregar a esta clase de controlador.
Atributos del modeloPrimero, agregaremos algunos atributos del modelo que necesitaremos en la página:
@ModelAttribute("allTypes") public List<Type> populateTypes() { return Arrays.asList(Type.ALL); } @ModelAttribute("allFeatures") public List<Feature> populateFeatures() { return Arrays.asList(Feature.ALL); } @ModelAttribute("allVarieties") public List<Variety> populateVarieties() { return this.varietyService.findAll(); } @ModelAttribute("allSeedStarters") public List<SeedStarter> populateSeedStarters() { return this.seedStarterService.findAll(); }
Métodos mapeadosY ahora la parte más importante del controlador son los métodos asignados: uno para mostrar la página del formulario y el otro para manejar la adición de nuevos objetos
SeedStarter .
@RequestMapping({"/","/seedstartermng"}) public String showSeedstarters(final SeedStarter seedStarter) { seedStarter.setDatePlanted(Calendar.getInstance().getTime()); return "seedstartermng"; } @RequestMapping(value="/seedstartermng", params={"save"}) public String saveSeedstarter( final SeedStarter seedStarter, final BindingResult bindingResult, final ModelMap model) { if (bindingResult.hasErrors()) { return "seedstartermng"; } this.seedStarterService.add(seedStarter); model.clear(); return "redirect:/seedstartermng"; }
4.5 Configuración del servicio de conversión
Para proporcionar un formato simple para los objetos
Date así como para los objetos
Variety en nuestra capa de vista, configuramos nuestra aplicación para que el objeto Spring
ConversionService se haya creado e inicializado (
WebMvcConfigurerAdapter extensible) utilizando un par de los objetos de formato que necesitamos.
Mira de nuevo:
@Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); }
Los
formateadores de Spring son implementaciones de la interfaz
org.springframework.format.Formatter . Para obtener más información sobre cómo funciona la infraestructura de conversión de Spring, consulte los documentos en
spring.io .
Veamos un
DateFormatter que formatea las fechas de acuerdo con la cadena de formato presente en la clave
date.format de nuestros
Messages.properties :
public class DateFormatter implements Formatter<Date> { @Autowired private MessageSource messageSource; public DateFormatter() { super(); } public Date parse(final String text, final Locale locale) throws ParseException { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.parse(text); } public String print(final Date object, final Locale locale) { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.format(object); } private SimpleDateFormat createDateFormat(final Locale locale) { final String format = this.messageSource.getMessage("date.format", null, locale); final SimpleDateFormat dateFormat = new SimpleDateFormat(format); dateFormat.setLenient(false); return dateFormat; } }
VarietyFormatter convierte automáticamente entre nuestros objetos
Variety y la forma en que queremos usarlos en nuestros formularios (principalmente por los valores de sus campos
id ):
public class VarietyFormatter implements Formatter<Variety> { @Autowired private VarietyService varietyService; public VarietyFormatter() { super(); } public Variety parse(final String text, final Locale locale) throws ParseException { final Integer varietyId = Integer.valueOf(text); return this.varietyService.findById(varietyId); } public String print(final Variety object, final Locale locale) { return (object != null ? object.getId().toString() : ""); } }
Aprenderemos más sobre cómo estas herramientas de formato afectan la forma en que mostramos nuestros datos en el futuro.