La evolución de las vistas HTML en Java: de Servlets a los motores de plantillas
Java ha ofrecido, a lo largo de los años, distintas maneras de generar interfaces web. Desde la construcción directa de HTML mediante Servlets hasta los motores de plantillas modernos, cada tecnología ha propuesto una forma diferente de abordar la presentación y su relación con el código Java.
Aunque actualmente gran parte de la atención se concentra en frameworks como Spring Boot y bibliotecas frontend como React, resulta interesante revisar cómo ha evolucionado el renderizado de HTML del lado del servidor.
El objetivo fundamental no ha cambiado: procesar una solicitud HTTP, obtener los datos necesarios y generar una respuesta que el navegador pueda interpretar.
Lo que ha cambiado es la manera de construir esa respuesta y de separar las responsabilidades dentro de una aplicación.
1. Servlets: generar HTML directamente desde Java
Una de las formas más directas de generar HTML es mediante un Servlet.
Utilizando el objeto HttpServletResponse, podemos obtener un PrintWriter y escribir directamente la respuesta:
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<h1>Hola mundo</h1>");
out.println("</body>");
out.println("</html>");Este enfoque permite controlar directamente la respuesta HTTP, pero tiene una limitación evidente: a medida que aumenta la complejidad de la interfaz, también aumenta la cantidad de instrucciones necesarias para construirla.
Generar tablas, formularios o estructuras HTML complejas mediante múltiples llamadas a println() puede convertirse en una tarea difícil de mantener.
Aunque las versiones modernas de Java permiten utilizar bloques de texto multilínea (Text Blocks), el problema arquitectónico continúa siendo el mismo: el código Java sigue siendo responsable de construir la estructura HTML.
Personalmente, considero que este enfoque puede seguir siendo útil para generar pequeños fragmentos HTML que serán solicitados mediante AJAX, aunque también existen alternativas basadas en plantillas.
2. JSP: HTML con contenido dinámico
JavaServer Pages (JSP) representó un cambio importante.
En lugar de construir HTML desde Java, permitió escribir HTML e incorporar instrucciones Java directamente en la página.
Por ejemplo:
<html>
<body>
<% out.print("Hola mundo"); %>
</body>
</html>El inconveniente aparecía cuando la aplicación comenzaba a crecer y el programador incorporaba importaciones, instanciación de objetos e incluso consultas a bases de datos dentro de las páginas.
<%@ page import="com.empresa.modelo.Producto" %>La vista podía terminar conteniendo tanto la estructura HTML como parte de la lógica de aplicación.
Esto generaba dificultades de mantenimiento y aumentaba el acoplamiento entre la presentación y el código Java.
Sin embargo, JSP no obligaba a trabajar de esa manera.
Con la utilización de Servlets como controladores, junto con JSTL y Expression Language (EL), era posible mantener las responsabilidades separadas.
Por ejemplo:
<c:forEach var="producto" items="${productos}">
<p>
<c:out value="${producto.nombre}" />
</p>
</c:forEach>De esta forma, JSP podía limitarse a presentar los datos entregados por un controlador, evitando insertar instrucciones Java directamente en la vista.
Curiosamente, los JSP son transformados y compilados internamente en Servlets. Lo que cambia es la forma en que el desarrollador escribe y organiza la presentación.
3. JSF: interfaces basadas en componentes
JavaServer Faces (JSF) propuso una filosofía diferente.
En lugar de trabajar únicamente con HTML dinámico, introdujo un modelo de programación basado en componentes de servidor, similar al utilizado por ASP.NET Web Forms.
Por ejemplo:
<h:form>
<h:inputText value="#{productoBean.nombre}" />
<h:commandButton
value="Guardar"
action="#{productoBean.guardar}" />
</h:form>Estos componentes se vinculan con propiedades y métodos de clases Java conocidas tradicionalmente como Managed Beans.
La principal ventaja es que desaparece la necesidad de incrustar bloques de código Java dentro del HTML.
Esto permite una mejor separación física entre las vistas y el código de aplicación.
Sin embargo, sigue existiendo una vinculación entre los componentes de la interfaz y las propiedades o métodos de los beans.
Además, JSF introduce un ciclo de vida propio para administrar eventos, validaciones, conversiones y estado de los componentes.
Por lo tanto, aunque simplifica determinadas tareas, también incorpora una capa de abstracción adicional.
4. Thymeleaf: HTML como protagonista
Thymeleaf representa otro enfoque para la generación de vistas.
Su característica principal es trabajar directamente con HTML, agregando atributos especiales que serán interpretados por el motor de plantillas.
Por ejemplo:
<table>
<tr th:each="producto : ${productos}">
<td th:text="${producto.nombre}"></td>
<td th:text="${producto.precio}"></td>
</tr>
</table>En este caso, la plantilla no necesita importar clases Java ni conocer cómo se obtuvieron los productos.
Solamente utiliza los datos que le entrega el controlador.
Esta separación resulta especialmente interesante desde el punto de vista arquitectónico.
La plantilla depende de los nombres y la estructura de los datos del modelo, pero no necesariamente de las clases concretas que implementan los servicios o la lógica de negocio.
Incluso es posible reemplazar un objeto Java por un DTO o un mapa de valores sin modificar la vista, siempre que se conserve el contrato de datos esperado.
Esto no significa que Thymeleaf elimine completamente el acoplamiento. Sus expresiones pueden acceder a propiedades e incluso invocar métodos.
La ventaja está en que facilita construir vistas orientadas principalmente a la presentación.
Otra característica interesante es que sus plantillas conservan una estructura HTML reconocible y pueden mostrar contenido de ejemplo sin ser procesadas previamente.
5. FreeMarker y Mustache: otras formas de trabajar con plantillas
Thymeleaf no es el único motor de plantillas disponible para Java.
FreeMarker y Mustache también permiten transformar datos en documentos HTML, aunque utilizan una sintaxis diferente.
FreeMarker utiliza directivas y expresiones:
<#list productos as producto>
<p>${producto.nombre}</p>
</#list>Su lenguaje de plantillas permite realizar iteraciones, condiciones y operaciones de formato relativamente complejas.
Mustache, en cambio, propone un enfoque más restringido, conocido como logic-less templates.
{{#productos}}
<p>{{nombre}}</p>
{{/productos}}Mustache intenta mantener las plantillas simples y reducir la cantidad de lógica que puede expresarse directamente dentro de ellas.
Ambas alternativas permiten trabajar con datos proporcionados desde Java sin necesidad de incorporar bloques de código Java dentro de las vistas.
La diferencia principal está en cuánto procesamiento de presentación permite realizar cada motor.
6. ¿Qué ha cambiado realmente?
Si observamos estas tecnologías desde una perspectiva histórica, podemos identificar diferentes maneras de resolver un problema común.
| Tecnología | Enfoque principal |
|---|---|
| Servlets | Generar HTML mediante instrucciones Java |
| JSP | Incorporar contenido dinámico en páginas HTML |
| JSF | Construir interfaces mediante componentes vinculados a beans |
| Thymeleaf | Procesar HTML mediante atributos de plantilla |
| FreeMarker | Procesar plantillas con expresiones y directivas |
| Mustache | Renderizar plantillas con una lógica mínima |
La evolución no puede entenderse simplemente como el reemplazo de una tecnología por otra.
En muchos casos, estas soluciones han coexistido y continúan utilizándose.
Tampoco resulta correcto afirmar que una tecnología garantiza por sí sola un menor acoplamiento.
Un JSP desarrollado con MVC, JSTL y EL puede mantener una adecuada separación de responsabilidades. Del mismo modo, una plantilla Thymeleaf puede terminar incorporando expresiones innecesariamente complejas si no se cuida su diseño.
La calidad de la separación depende tanto de las capacidades de la tecnología como de las decisiones arquitectónicas del desarrollador.
7. ¿Y dónde quedan los Frameworks?
Es importante distinguir entre el framework utilizado para desarrollar una aplicación y la tecnología encargada de generar sus vistas.
Los frameworks facilitan la configuración y ejecución de aplicaciones Java, pero no obliga a utilizar un único motor de presentación.
Es posible desarrollar aplicaciones con frameworks utilizando Thymeleaf, FreeMarker, Mustache y también otras tecnologías como JSP o JSF, estas últimas con consideraciones particulares de integración.
Asimismo, Thymeleaf o FreeMarker pueden utilizarse directamente con Servlets y servidores como Jetty o Tomcat, sin depender de cualquier framework.
Por lo tanto, elegir el framework web y elegir el mecanismo de generación de HTML son decisiones relacionadas, pero diferentes.
8. El renderizado del lado del servidor continúa vigente
Actualmente también es habitual desarrollar un frontend independiente mediante React, Angular o Vue y utilizar Java exclusivamente para exponer servicios mediante API REST.
En esta arquitectura, Java entrega principalmente datos y el navegador asume una mayor responsabilidad en la construcción de la interfaz.
Sin embargo, esto no significa que el renderizado del lado del servidor haya dejado de ser útil.
Para numerosos sistemas administrativos, aplicaciones empresariales y proyectos donde la generación de HTML desde el servidor resuelve adecuadamente las necesidades del negocio, los motores de plantillas continúan siendo alternativas perfectamente válidas.
Incluso es posible combinar páginas generadas desde el servidor con actualizaciones parciales mediante AJAX.
Conclusión
A lo largo de su historia, Java ha ofrecido diferentes mecanismos para construir interfaces web.
Hemos pasado de escribir HTML directamente mediante instrucciones Java a utilizar páginas dinámicas, componentes de servidor y motores de plantillas.
Cada enfoque ha intentado mejorar aspectos como la productividad, la legibilidad, la reutilización y la separación de responsabilidades.
Sin embargo, considero que el aprendizaje más importante no consiste en determinar cuál tecnología es superior, sino en comprender cómo cada una resuelve la relación entre los datos, la lógica de aplicación y la presentación.
Al final, el navegador continúa recibiendo HTML. Lo que ha evolucionado es la forma en que lo generamos, organizamos y mantenemos desde Java.
Comentarios
Publicar un comentario