Thymeleaf转Flying-Saucer生成PDF时JQuery代码未执行问题
核心原因很简单:Flying-Saucer(也就是你用的ITextRenderer)根本不支持执行JavaScript。它本质是个静态XHTML/CSS渲染器,只会老老实实解析你给它的最终XHTML结构和CSS样式,完全不会去碰页面里的JS代码——不管是jQuery还是原生JS都没戏。
而Thymeleaf的角色只是把模板和数据合并成静态HTML文本,它也不负责执行JS。所以你最后传给Flying-Saucer的XHTML里虽然带着jQuery代码,但这个渲染器根本看不懂、也不会去执行它。
既然JS走不通,咱们换静态处理的方式来实现“数值小于0时对应TD变红”的需求:
1. 在Thymeleaf模板里直接处理(最推荐)
利用Thymeleaf的表达式能力,渲染HTML时直接给符合条件的TD加样式类,生成的HTML本身就带正确样式,不需要依赖任何JS。
修改你的Thymeleaf模板:
<table class="dcf"> <!-- 示例行,根据你的实际数据变量调整 --> <tr> <td th:class="${yourData.value1 < 0 ? 'text-red' : ''}"> <span th:text="${yourData.value1}">-500</span> € </td> <td th:class="${yourData.value2 < 0 ? 'text-red' : ''}"> <span th:text="${yourData.value2}">-500</span> </td> </tr> <!-- 其他行同理 --> </table> <style> .text-red { color: red !important; /* 加!important确保样式生效 */ } </style>
这种方式逻辑清晰,性能也最好,不需要额外的后续处理步骤。
2. 在Java代码里修改渲染后的HTML
如果不想改模板,可以用Jsoup库解析Thymeleaf生成的HTML,手动给符合条件的TD加样式:
首先引入Jsoup依赖(Maven为例):
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.17.2</version> </dependency>
然后修改你的Java代码:
// 先通过Thymeleaf渲染出HTML String renderedHtmlContent = templateEngine.process("bm001", context); // 用Jsoup解析HTML Document doc = Jsoup.parse(renderedHtmlContent); // 找到所有目标span Elements spans = doc.select(".dcf td span"); for (Element span : spans) { // 处理欧洲格式的数值:把千分位的点去掉,逗号换成小数点 String cleanValue = span.text().replace(".", "").replace(",", "."); try { double num = Double.parseDouble(cleanValue); if (num < 0) { // 给父元素TD加红色样式 span.parent().attr("style", "color: red;"); } } catch (NumberFormatException e) { // 处理非数值的异常情况 e.printStackTrace(); } } // 把修改后的HTML转成XHTML格式 String xHtml = doc.html(); // 后续继续用Flying-Saucer生成PDF...
3. 用Flying-Saucer支持的CSS选择器(有限场景可用)
Flying-Saucer对CSS的支持不算完全,但可以试试:has()选择器(注意要确认你的版本是否支持):
.dcf td:has(span:contains('-')) { color: red; }
这种方式的局限性很大:如果负数没有用负号表示就会失效,而且旧版本的Flying-Saucer可能不支持:has(),需要测试验证。
Flying-Saucer不支持JS执行是核心问题,所以必须用静态处理的方式。最推荐第一种Thymeleaf模板内处理的方案,简单高效,逻辑也最直观。
内容的提问来源于stack exchange,提问作者Krbch

