tutorial ejemplo curso java spring thymeleaf

java - ejemplo - thymeleaf tutorial



¿Soporte XHTML Basic para Thymeleaf? (1)

Estoy tratando de obtener Spring 4.1.9 y Thymeleaf 2.1.5 para representar páginas XHTML Basic 1.1, que tienen el siguiente preámbulo:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

El simple uso de esto en una plantilla no funciona, ya que Thymeleaf no reconoce el doctype.

org.thymeleaf.exceptions.TemplateProcessingException: entidad no admitida solicitada con PUBLICID "- // W3C // DTD XHTML Basic 1.1 // EN" y SYSTEMID " http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd ". Asegúrese de que su dialecto provea la correspondiente org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry (índice: 1)

Preparar

Revisé la documentación y el código fuente de la extensión Thymeleaf y, utilizando ese punto de partida, definí un nuevo dialecto heredado de SpringStandardDialect Descubrí los módulos faltantes mediante prueba y error, descargándolos de w3.org y agregándolos al directorio de recursos de mi proyecto:

XhtmlBasicDialect.java

import java.util.LinkedHashSet; import java.util.Set; import org.thymeleaf.doctype.DocTypeIdentifier; import org.thymeleaf.doctype.resolution.ClassLoaderDocTypeResolutionEntry; import org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry; import org.thymeleaf.spring4.dialect.SpringStandardDialect; public class XhtmlBasicDialect extends SpringStandardDialect { private static final String DTD_STANDARD_PATH = "org/thymeleaf/dtd/standard/"; private static final DocTypeIdentifier XHTML_BASIC_11_PUBLICID = DocTypeIdentifier.forValue("-//W3C//DTD XHTML Basic 1.1//EN"); private static final DocTypeIdentifier XHTML_BASIC_11_SYSTEMID = DocTypeIdentifier.forValue("http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"); private static final DocTypeIdentifier ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ENTITIES XHTML Basic 1.1 Document Model 1.0//EN"); private static final DocTypeIdentifier ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN"); private static final DocTypeIdentifier ELEMENTS_XHTML_INPUTMODE_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Inputmode 1.0//EN"); private static final DocTypeIdentifier ELEMENTS_XHTML_TARGET_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Target 1.0//EN"); private static final IDocTypeResolutionEntry XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(XHTML_BASIC_11_PUBLICID, XHTML_BASIC_11_SYSTEMID, DTD_STANDARD_PATH + "xhtml-basic11.dtd"); private static final IDocTypeResolutionEntry ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic11-model-1.mod"); private static final IDocTypeResolutionEntry ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic-table-1.mod"); private static final IDocTypeResolutionEntry ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_INPUTMODE_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-inputmode-1.mod"); private static final IDocTypeResolutionEntry ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_TARGET_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-target-1.mod"); @Override protected Set<IDocTypeResolutionEntry> getAdditionalDocTypeResolutionEntries() { final Set<IDocTypeResolutionEntry> docTypeResolutionEntries = new LinkedHashSet<IDocTypeResolutionEntry>(); docTypeResolutionEntries.add(XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY); docTypeResolutionEntries.add(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY); docTypeResolutionEntries.add(ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY); docTypeResolutionEntries.add(ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY); docTypeResolutionEntries.add(ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY); return docTypeResolutionEntries; } }

Configuro el dialecto personalizado de la siguiente manera:

mvc-config.xml

... <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix" value=".xhtml" /> <property name="characterEncoding" value="UTF-8" /> <property name="templateMode" value="XHTML" /> <property name="xhtmlTemplateModePatterns" value="*.xhtml" /> </bean> <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver" /> <property name="additionalDialects"> <set> <bean class="demo.XhtmlBasicDialect" /> </set> </property> </bean> <bean id="xhtmlViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine" /> <property name="characterEncoding" value="UTF-8" /> <property name="contentType" value="application/xhtml+xml" /> </bean> ...

Mi plantilla es la siguiente:

DemoTemplate.xhtml

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <title>Demo</title> <link th:href="${''style'' + ''.css''}" rel="stylesheet" type="text/css"/> </head> <body> <div> <p>Demo content</p> </div> </body> </html>

El problema

A primera vista, esto parece funcionar bien, excepto que al XHTML resultante le falta el encabezado XML y tiene varios atributos adicionales que se agregan a cada elemento.

Salida renderizada:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="-//W3C//DTD XHTML Basic 1.1//EN"> <head xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <title xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Demo</title> <link rel="stylesheet" type="text/css" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve" href="style.css" /> </head> <body xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve"> <div xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve"> <p xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">Demo content</p> </div> </body> </html>

Esto no coincide exactamente con el preámbulo básico de XHTML; Por un lado, me gustaría mantener la declaración XML <?xml version="1.0" encoding="utf-8"?>

Más importante aún, no quiero que xmlns="http://www.w3.org/1999/xhtml" , xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" , y xml:space="preserve" atributos que se agregarán a casi todos los elementos. También hay un atributo version="-//W3C//DTD XHTML Basic 1.1//EN" agregado al elemento <html> .

¿Estoy haciendo algo mal, necesito configurar algo de manera diferente o me falta algo del dialecto personalizado?


Bueno, no tengo evidencia "canónica" de que las plantillas de XHTML Basic no puedan manejarse de la manera que usted quiere con Thymeleaf 2.x, y probablemente haya un esfuerzo con suficiente esfuerzo. Pero vi eso:

Esto, junto con mis propios esfuerzos por hacer que algo funcione, me lleva a creer que el manejo de XHTML en Thymeleaf 2.X nunca fue completamente horneado. Sin embargo, parece funcionar bien en 3.0 sin ningún esfuerzo especial. Simplemente configure un ViewResolver siguiente manera:

<bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring4.SpringTemplateEngine"> <property name="enableSpringELCompiler" value="true"/> <property name="templateResolver"> <bean class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/"/> <property name="suffix" value=".xhtml"/> <property name="templateMode" value="XML"/> </bean> </property> </bean> </property> </bean>

Publiqué un ejemplo completo de trabajo en github .