Softtek Softtek
  • Our experience
  • Overview
  • Insights
  • Blog
  • Newsroom
  • Careers
  • Contact us
softtek Language Selector
ENGLISH
EUROPE / EN
ESPAÑOL
EUROPA / ES
PORTUGUÊS
中文(简体)
Search button
AI
APPROACH
INDUSTRIES
SERVICES & SOLUTIONS
TRANSCEND
Softtek GenAI
FRIDA AI for Software Engineering
Service Transformation
Portfolio Transformation
Digital Acceleration
Our Work
Agribusiness
Airlines
Automotive
Banking & Financial Services
Consumer Packaged Goods
Energy & Utilities
Fitness & Wellness
Gaming
Government & Public Sector
Higher Education
Healthcare
Industrial
Insurance
Media & Entertainment
Oil & Gas
Pharma & Beauty
Professional Sports
Restaurant & Hospitality
Retail
Technology
Telecommunications
Transportation & Logistics
Digital Solutions
Digital Optimization
Digital Sales
Data Masking Solution
IT Cost Optimization
Fan Engagement Ecosystem
Softtek Digital Enablers
DIEGO
blauLabs
Business OnDemand
Click2Sync Omnichannel
Automotive Digital Assistant
Guest Engagement
Socializer
Collaborative Commuting
Workplace Management
Application Services
Software Development
Quality Engineering
Application Management
Application Services
Cloud & DevOps
Cloud Services
IT Infrastructure
Digital Security
DevOps
Data & Automation
Data and AI
Intelligent Automation
Services Transformation
Core Modernization
Next-Gen IT Operations
Platform Services
AWS
SAP
Microsoft
Salesforce
ServiceNow
Atlassian
BlueYonder
Sustainability by Softtek
Softtek
Language selector
search button
AI
Softtek GenAI
FRIDA AI for Software Engineering
APPROACH
Service Transformation
Portfolio Transformation
Digital Acceleration
Our Work
INDUSTRIES
Agribusiness
Airlines
Automotive
Banking & Financial Services
Consumer Packaged Goods
Energy & Utilities
Fitness & Wellness
Gaming
Government & Public Sector
Higher Education
Healthcare
Industrial
Insurance
Media & Entertainment
Oil & Gas
Pharma & Beauty
Professional Sports
Restaurant & Hospitality
Retail
Technology
Telecommunications
Transportation & Logistics
SERVICES & SOLUTIONS
Digital Solutions
Digital Optimization
Digital Sales
Data Masking Solution
IT Cost Optimization
Fan Engagement Ecosystem
Softtek Digital Enablers
DIEGO
blauLabs
Business OnDemand
Click2Sync Omnichannel
Automotive Digital Assistant
Guest Engagement
Socializer
Collaborative Commuting
Workplace Management
Application Services
Software Development
Quality Engineering
Application Management
Application Services
Cloud & DevOps
Cloud Services
IT Infrastructure
Digital Security
DevOps
Data & Automation
Data and AI
Intelligent Automation
Services Transformation
Core Modernization
Next-Gen IT Operations
Platform Services
AWS
SAP
Microsoft
Salesforce
ServiceNow
Atlassian
BlueYonder
TRANSCEND
Sustainability by Softtek
Our experience
Overview
Insights
Blog
Newsroom
Careers
Contact us
Presencia Global
ENGLISH
EUROPE / EN
ESPAÑOL
EUROPA / ES
PORTUGUÊS
中文(简体)
Softtek Blog

Thymeleaf como alternativa MVC

Autor
Author Sebastian Castillo Rodríguez
Publicado el:
feb 26, 2018
Tiempo de lectura:
feb 2018
|
SHARE
Share on LinkedIn
Share on X
Share on Facebook
SHARE
Share on LinkedIn
Share on X
Share on Facebook

 

Hace 5 años escribí por primera vez sobre Thymeleaf y hoy, con el proyecto ya bastante más maduro, vuelvo a hacerlo de nuevo en estas líneas: Qué es, qué ventajas ofrece, y un sencillo ejemplo práctico.

Thymeleaf es un motor de plantillas Java para aplicaciones, tanto web como standalone, construido sobre estándares HTML5, por lo que es compatible con la inmensa mayoría de navegadores. Entre sus principales características cabe destacar su flexibilidad y su alto rendimiento que, junto con su facilidad de aprendizaje y su poco intrusismo en el marcado lo convierten en una alternativa real a otras opciones más populares como JSP.

Para los que trabajamos con Spring Framework, Thymeleaf nos ofrece un set completo de integración que nos permite incorporalo dentro del patrón MVC:

  • Los @Controller de Spring pueden redireccionarse a las plantillas Thymeleaf de la misma forma que, por defecto, se hacen a JSP.

  • Permite el uso de Spring Expression Language (Spring EL)

  • Los formularios se integran perfectamente con los beans y los result bindings de Spring, así como con los manejadores de errores.

  • Permite internacionalización a través de los típicos MessageSource de Spring.

Con todo esto, y como veremos más adelante en el ejemplo, la integración de Thymeleaf con Spring es tremendamente sencilla y casi transparente para el desarrollador.

Como curiosidad, durante la SpringOne de 2014 el equipo de Pivotal recomendó el uso de Thymeleaf como motor de plantillas y, para demostrar su integración, anunciaron que la propia web de spring.io está construida con Thymeleaf. Desde entonces, esa recomendación se repite en muchos de los nuevos tutoriales del site oficial de Spring Framework.

Ok, basta de teoría. Vamos a ver cómo funciona. En este post mostraré un ejemplo muy sencillo porque, de forma paralela a mi proyecto actual, he arrancado un side project basado en Thymeleaf que espero que acabe dando sus frutos en forma de webinar o bien de un post más avanzado sobre plantillas en las próximas semanas (aprovecho para lanzarle el guante a mis compañeros ;).

En este ejemplo, vamos a crear una pequeña app para realizar sorteos. En la pantalla inicial se deberá rellenar un formulario con una lista de participantes así como el número de participaciones que tiene cada uno. Al hacer el submit, devolveremos una tabla con todos los participantes ordenados aleatoriamente, teniendo en cuenta que, a mayor número de participaciones, más probabilidades tiene de estar más arriba.

Las fuentes del proyecto podéis descargarlas en mi Github: https://github.com/sebascastillo89/thymeleafdemo

 

(1) Proyecto Maven y Spring Boot

Generamos un proyecto con Spring Boot a través de Spring Initializr, indicando como dependencias Web, que incorporará capacidades Spring MVC y un servidor Tomcat embebido a nuestra aplicación y Thymeleaf, que incorporará nuestro motor de plantilla:

thymeleaf_project.png

Una vez generado el proyecto, podemos descomprimirlo, compilarlo usando Maven e importarlo en nuestro IDE Eclipse.

(2) Controlador

Vamos a crear el controlador que implemente la lógica de nuestro sorteo, RaffleController:


package es.secaro.thymeleafdemo.controller;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import es.secaro.thymeleafdemo.dto.Raffle;

@Controller
public class RaffleController {
	
	@GetMapping("/raffle")
	public String raffleForm(Model model) {
		model.addAttribute("raffle", new Raffle());
		return "raffle";
	}
	
	@PostMapping("/raffle")
	public String raffleSubmit(@ModelAttribute Raffle raffle) {
		
		String candidates = raffle.getCandidates();		
		List winners = doRaffle(asList(candidates));

		raffle.setWinners(winners);
		return "result";
	}

	private List doRaffle(List candidates) {
		
		Random random = new Random();
		List winners = new ArrayList();		
		
		int winnerSize = new HashSet(candidates).size(); // HashSet elimina duplicados		
		while(winnerSize>0){
			String nextWinner = candidates.get(random.nextInt(candidates.size()));	
			while(winners.contains(nextWinner)){
				nextWinner = candidates.get(random.nextInt(candidates.size()));	
			}
			winners.add(nextWinner);
			winnerSize--;
		}
		return winners;
	}

	private List asList(String candidates) {
		
		List candidatesAsList = new ArrayList();
			for (String line : candidates.split("\\n")) {
				
				String[] split = line.split(",");
				String name = split[0].trim();
				int tickets = Integer.valueOf(split[1].trim());

				while (tickets > 0) {
					candidatesAsList.add(name);
					tickets--;
				}
			}
			return candidatesAsList;		
	}

}

Para que nuestro controlador intercepte las peticiones HTTP basta con decorar nuestra clase con @Controller.

Cuando accedamos a través del navegador (petición GET) a /raffle el método raffleForm() decorado con @GetMapping interceptará la petición y añadira un objeto Raffle a nuestro componente modelo de MVC.

Cuando hagamos submit de nuestro formulario (petición POST) el método raffleSubmit() decorado con @PostMapping interceptará la petición, realizará el sorteo y añadirá la lista ordenada de ganadores al modelo.

Ambos métodos controladores devuelven una cadena de texto (p.e: return "raffle";). Dentro del patrón MVC (Modelo Vista Controlador) esta cadena se utilizará para identificar la vista que queremos procesar (en este caso raffle.html).

Los métodos doRaffle y asList son dos métodos privados de utilidad que realizan el sorteo y convierten la lista de candidatos en un objeto List<String> respectivamente. 

Por último, para representar a nuestro modelo usamos el objeto Raffle, que es un simple POJO que contiene la cadena de candidatos que tomamos como entrada y la lista ordenada de ganadores que mostramos a la salida:


package es.secaro.thymeleafdemo.dto;

import java.util.List;

public class Raffle {

	private String candidates;
	private List winners;

	public String getCandidates() {
		return candidates;
	}

	public void setCandidates(String candidates) {
		this.candidates = candidates;
	}

	public List getWinners() {
		return winners;
	}

	public void setWinners(List winners) {
		this.winners = winners;
	}

} 

 

(3) raffle.html

Vamos con nuestra pantalla de inicio, dóide únicamente recibiremos la lista de candidatos y el número de participaciones o tickets que tiene cada uno. Evidentemente, a mayor número de participaciones más probabilidades tendrán de estar en lo más alto de la tabla de ganadores. Veremos como el binding o unión de nuestro formulario con nuestro controlador y con nuestro modeloes bastante sencillo:

thymeleaf_raffle.png

En primer lugar, th:action="@{/raffle}" envía el submit de nuestro formulario mediante un POST a /raffle, que es la URL que tenemos configurada para que intercepte nuestro Controlador (ver @PostMapping en RaffleController).

En segundo lugar, th:object="${raffle}" declara el objeto modelo contra el que haremos el binding para recopilar los datos del formulario, en este caso Raffle.java

Por último, th:field="*{candidates}" hace el binding entre el campo del formulario anotado y el campo candidates de nuestro objeto modelo.

 

(4) result.html

Por último, vamos a generar nuestra página de respuesta result.html, donde mostraremos la tabla de todos los participantes ordenados por sorteo, teniendo más probabilidad de estar arriba (ganador) aquellos que más participaciones tienen.

Aprovecharemos este pequeño ejemplo para ver cómo iterar una lista con Thymeleaf:

thymeleaf_result.png

Usamos th:each="winner: ${raffle.winners}" para iterar la List de nuestro modelo Raffle. Añadimos una nueva fila a nuestra tabla con cada uno de los elementos de esa lista con th:text="${winner}".

 

(5) Probando nuestra app.

Al tratarse de un proyecto Spring Boot con un servidor tomcat embebido, bastará con compilar nuestro proyecto (mvn package) y ejecutar el jar generado (java -jar target/thymeleafdemo-0.0.1-SNAPSHOT.jar). Ambos comandos se deben ejecutar sobre la raíz del proyecto.

Para saber más sobre cómo generar, compilar y desplegar una aplicación con Spring Boot os recomiendo echar un vistazo al webinar: Construyendo un API Rest con Spring, MongoDB & Heroku

Si vamos directamente a localhost:8080/raffle veremos nuestro formulario, donde podemos ejecutar un ejemplo:

thymeleaf_demoRaffle.png

Si realizamos el sorteo, obtenemos la tabla de ganadores:

thymeleaf_demoResults.png

Hasta aquí este sencillo ejemplo de integración de Thymeleaf con Spring MVC. En próximos post daremos un paso más en el marcado con Thymeleaf y conoceremos la suite de pruebas de la herramienta.

Puede encontrar las fuentes del ejemplo aquí: https://github.com/sebascastillo89/thymeleafdemo

Related posts

jwtlogo
ene 8, 2019
Autenticación de APIs basada en tokens con Spring y JWT
architecture-asian-bird-s-eye-view-186537 (1)
ago 29, 2019
Introducción a la Concurrencia en Java (I)
ARPTesting.png
oct 24, 2017
Guía rápida y definitiva para iniciarse con testing unitario

Let’s stay in touch!

Get Insights from our experts delivered right to your inbox!

Follow us:
Softtek LinkedIn
Softtek Twitter
Softtek Facebook
Softtek Instagram
Softtek Instagram
Follow us:
Softtek LinkedIn
Softtek Twitter
Softtek Facebook
Softtek Instagram
Softtek Instagram

© Valores Corporativos Softtek S.A. de C.V. 2025.
privacy notice
legal disclaimer
code of ethics
our policies
webmaster@softtek.com