En aplicaciones basadas en Spring MVC, a menudo se requiere que un controlador devuelva una cadena de texto que contenga código HTML completo, para que el navegador la renderiec como una página web. Este artículo presenta dos técnicas principales para lograrlo, además de un enfoque adicional para manipular HTML usando Jsoup.
Técnica 1: Escritura directa con HttpServletResponse
Este método consiste en escribir la cadena HTML en el flujo de salida de la respuesta HTTP, configurando previamente los encabezados para indicar al navegador el tipo de contenido.
PrintWriter writer = null;
response.setContentType("text/html; charset=UTF-8");
try {
writer = response.getWriter();
writer.print(htmlContent);
writer.flush();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
Técnica 2: Uso de @ResponseBody con conversión de mensajes
Se puede emplear la anotación @ResponseBody en el método del controlador y definir el atributo produces para especificar el tipo de contenido. Adicionalmente, es necesario configurar los conversores de mensajes en Spring para evitar comillas indeseadas alrededor de la cadena.
@RequestMapping(value = "/paginaGenerada", produces = {MediaType.TEXT_HTML_VALUE})
@ResponseBody
public String paginaGenerada() {
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("<meta charset="\"UTF-8\""></meta>");
htmlBuilder.append("<title>Contenido Dinámico</title>Datos generados en el servidor");
return htmlBuilder.toString();
}
Para solucionar el problema de comillas, se debe incluir la siguiente configuración en el archivo spring-mvc.xml:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
Manipulación de HTML con Jsoup
Jsoup es una biblioteca de Java que facilita el parseo y la modificación de cadenas HTML. Primero, se debe añadir la dependencia correspondiente al proyecto:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
A continuación, se muestra un ejemplo de controlador que obtiene HTML de una fuente externa, lo modifica y lo devuelve al navegador:
@RequestMapping("procesarHtml")
public void procesarHtml(HttpServletRequest request, HttpServletResponse response) throws IOException {
String targetUrl = "http://localhost:8080/recurso/pagina.html";
String rawHtml = HttpClientUtil.fetchContent(targetUrl);
Document document = Jsoup.parse(rawHtml);
Elements tableElements = document.select("table");
for (Element table : tableElements) {
table.html("Contenido alterado");
}
response.setContentType("text/html; charset=utf-8");
PrintWriter outputWriter = response.getWriter();
outputWriter.print(document.outerHtml());
}