如何在JHipster应用中配置Thymeleaf PDF模板解析器并区分使用
解决方法:给邮件和PDF分别配置独立的TemplateEngine
我之前在JHipster项目里也碰到过一模一样的需求,其实核心就是把两个模板解析器分别绑定到不同的TemplateEngine实例上,这样用的时候直接指定对应的Engine就行,完全不会搞混。
1. 完善Thymeleaf配置类
修改你的ThymeleafConfiguration,添加两个命名的TemplateEngine Bean,每个Bean只关联对应的解析器:
@Configuration public class ThymeleafConfiguration { // 邮件模板解析器:对应templates/mails/目录 @Bean public ClassLoaderTemplateResolver emailTemplateResolver() { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setPrefix("classpath:/templates/mails/"); resolver.setSuffix(".html"); resolver.setTemplateMode(TemplateMode.HTML); resolver.setCharacterEncoding("UTF-8"); resolver.setCheckExistence(true); // 检查模板是否存在,避免找不到时报错 return resolver; } // PDF模板解析器:对应templates/pdf/目录 @Bean public ClassLoaderTemplateResolver pdfTemplateResolver() { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setPrefix("classpath:/templates/pdf/"); resolver.setSuffix(".html"); // 生成PDF建议用严格的HTML或XML模式,避免渲染问题 resolver.setTemplateMode(TemplateMode.HTML); resolver.setCharacterEncoding("UTF-8"); resolver.setCheckExistence(true); return resolver; } // 邮件专用TemplateEngine @Bean(name = "emailTemplateEngine") public SpringTemplateEngine emailTemplateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.addTemplateResolver(emailTemplateResolver()); // 如果邮件模板需要Spring方言(比如sec:authentication),可以在这里添加 // engine.addDialect(new SpringSecurityDialect()); return engine; } // PDF专用TemplateEngine @Bean(name = "pdfTemplateEngine") public SpringTemplateEngine pdfTemplateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.addTemplateResolver(pdfTemplateResolver()); // 如果PDF模板需要布局方言或其他扩展,在这里添加 // engine.addDialect(new LayoutDialect()); return engine; } }
2. 在邮件服务中使用邮件TemplateEngine
在你的邮件发送服务类里,通过@Qualifier指定注入"emailTemplateEngine",然后直接用它渲染邮件模板:
@Service public class MailService { private final SpringTemplateEngine emailTemplateEngine; // 构造注入时指定要使用的TemplateEngine public MailService(@Qualifier("emailTemplateEngine") SpringTemplateEngine emailTemplateEngine) { this.emailTemplateEngine = emailTemplateEngine; } public void sendWelcomeEmail(String username) { Context context = new Context(); context.setVariable("username", username); // 直接传模板名称(对应templates/mails/welcome.html) String emailContent = emailTemplateEngine.process("welcome", context); // 后续的邮件发送逻辑(比如用JavaMailSender发送) // ... } }
3. 在PDF生成服务中使用PDF TemplateEngine
同样,在PDF生成类里注入"pdfTemplateEngine",渲染PDF模板后再转成PDF文件:
@Service public class PdfGeneratorService { private final SpringTemplateEngine pdfTemplateEngine; public PdfGeneratorService(@Qualifier("pdfTemplateEngine") SpringTemplateEngine pdfTemplateEngine) { this.pdfTemplateEngine = pdfTemplateEngine; } public byte[] generateInvoicePdf(Invoice invoice) { Context context = new Context(); context.setVariable("invoice", invoice); context.setVariable("totalAmount", invoice.calculateTotal()); // 渲染PDF模板(对应templates/pdf/invoice.html) String htmlContent = pdfTemplateEngine.process("invoice", context); // 用PDF库(比如iText 7)把HTML转成PDF try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { PdfWriter writer = new PdfWriter(outputStream); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); HtmlConverter.convertToDocument(htmlContent, doc); doc.close(); return outputStream.toByteArray(); } catch (IOException e) { throw new RuntimeException("Failed to generate PDF", e); } } }
为什么这样做?
每个TemplateEngine实例只绑定了自己对应的解析器,所以调用process()方法时,只会去对应的模板目录查找文件,完全不会出现解析器混用的问题。这种方式在JHipster项目里非常清晰,也方便后续扩展(比如给PDF模板添加专门的方言)。
最后确认一下你的模板文件路径:
- 邮件模板放在
src/main/resources/templates/mails/ - PDF模板放在
src/main/resources/templates/pdf/
内容的提问来源于stack exchange,提问作者tibi
相关产品推荐
相关产品推荐

