Thymeleaf处理XML模板时UTF-8编码异常问题求助
Thymeleaf渲染XML模板时非ASCII字符被转义为十六进制实体的问题
问题描述
我正尝试使用Thymeleaf对以下XML模板进行简单变量替换:
<?xml version="1.0" encoding="UTF-8"?> <note> <to> ARABIC: [[${TEST_AR}]] HEBREW: [[${TEST_HE}]] CHINESE (MANDARIN): [[${TEST_CH}]] </to> </note>
已配置模板、Java源码、OutputStreamWriter、ClassLoaderTemplateResolver及Maven均为UTF-8编码,但发现Thymeleaf渲染XML模板时,阿拉伯语、希伯来语等非ASCII字符被转换为十六进制实体;而使用TEXT模板(修改文件扩展名及对应代码行)时,UTF-8输出正常。
正常输出示例
<?xml version="1.0" encoding="UTF-8"?> <note> <to> ARABIC: كتابة مفهومة من قبل اغل HEBREW: ניסיון CHINESE (MANDARIN): </to> </note>
异常输出示例
<?xml version="1.0" encoding="UTF-8"?> <note> <to> ARABIC: كتابة مفهومة من قبل اغل HEBREW: ניסיון CHINESE (MANDARIN): </to> </note>
完整可复现代码
package com.xerox; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; public class TestThymeleafUTF8 { public static void main(String[] args) { try { TemplateEngine templateEngine = new TemplateEngine(); ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setCharacterEncoding("UTF-8"); resolver.setTemplateMode(TemplateMode.TEXT); templateEngine.setTemplateResolver(resolver); Context ct = new Context(); ct.setVariable("TEST_AR", "كتابة مفهومة من قبل اغل"); ct.setVariable("TEST_HE", "ניסיון"); ct.setVariable("TEST_CN", "王明是中国人。"); ct.setVariable("currentDate", LocalDateTime.now().toString()); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("test_output.txt"), StandardCharsets.UTF_8)); templateEngine.process("test_template.txt", ct,out); } catch (Exception e) { System.out.println(e); } } }
POM配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xerox</groupId> <artifactId>testUTF</artifactId> <version>0.0.1-SNAPSHOT</version> <name>testUTF</name> <description>thymeleaf testUTF</description> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.1.0.RELEASE</version> </dependency> </dependencies> </project>
请问这是Thymeleaf的UTF-8 XML Bug,还是我遗漏了必要配置?
原因与解决方案
这不是Thymeleaf的Bug,是XML模板模式下的默认行为。Thymeleaf在XML模式中会自动转义非ASCII字符为实体引用,这是为了遵循XML规范——尽管UTF-8支持这些字符,但XML允许用实体表示字符,引擎默认启用了该逻辑;而TEXT模式无XML语法约束,直接输出原始UTF-8字符。
解决方法
方法1:局部关闭变量转义
将模板中的表达式从[[${变量名}]]改为[(${变量名})],Thymeleaf会对该表达式的输出关闭转义:
<?xml version="1.0" encoding="UTF-8"?> <note> <to> ARABIC: [(${TEST_AR})] HEBREW: [(${TEST_HE})] CHINESE (MANDARIN): [(${TEST_CH})] </to> </note>
方法2:全局配置转义规则(不推荐)
若需全局禁用XML模板的非ASCII字符转义,可自定义XmlTemplateModeHandler,但该方式复杂度高,仅适合批量处理场景。
注意事项
关闭转义后需确保变量内容不含XML特殊字符(如<、>、&),否则会破坏XML合法性。若变量可能包含这类字符,建议仅对确定安全的非ASCII字符使用无转义表达式,或先对特殊字符做转义处理。
内容的提问来源于stack exchange,提问作者JavaSheriff
相关产品推荐
相关产品推荐

