我想写一些像:
@Autowired
private SpringTemplateEngine engine;
....
// Thymeleaf Context
WebContext thymeleafContext = new WebContext(request, response, request.getServletContext(), locale);
// cached html of a thymeleaf template file
String cachedHtml=....
// process the cached html
String html=engine.process(cachedHtml, thymeleafContext);
默认情况下,[process]方法无法执行此操作。我可以从文档中了解到我需要一个特殊的模板解析器:
为了执行模板,将使用进程(String,IContext)方法: final String result = templateEngine.process(" mytemplate",ctx); " mytemplate" String参数是模板名称,它将以模板解析器配置的方式与模板本身的物理/逻辑位置相关。
有谁知道如何解决我的问题?
目标是将Thymeleaf模板(文件)缓存在字符串中,然后处理这些字符串而不是文件。
答案 0 :(得分:11)
我们最终使用的解决方案包含一个新的IResourceResolver
,其中包含自定义Context
而非自定义TemplateResolver
。我们选择这个是因为我们仍然希望在大多数情况下使用类路径扫描,但偶尔会有动态内容。
以下显示我们是如何做到的:
public class StringAndClassLoaderResourceResolver implements IResourceResolver {
public StringAndClassLoaderResourceResolver() {
super();
}
public String getName() {
return getClass().getName().toUpperCase();
}
public InputStream getResourceAsStream(final TemplateProcessingParameters params, final String resourceName) {
Validate.notNull(resourceName, "Resource name cannot be null");
if( StringContext.class.isAssignableFrom( params.getContext().getClass() ) ){
String content = ((StringContext)params.getContext()).getContent();
return IOUtils.toInputStream(content);
}
return ClassLoaderUtils.getClassLoader(ClassLoaderResourceResolver.class).getResourceAsStream(resourceName);
}
public static class StringContext extends Context{
private final String content;
public StringContext(String content) {
this.content = content;
}
public StringContext(String content, Locale locale) {
super(locale);
this.content = content;
}
public StringContext(String content, Locale locale, Map<String, ?> variables) {
super(locale, variables);
this.content = content;
}
public String getContent() {
return content;
}
}
测试用例
public class StringAndClassLoaderResourceResolverTest {
private static SpringTemplateEngine templateEngine;
@BeforeClass
public static void setup(){
TemplateResolver resolver = new TemplateResolver();
resolver.setResourceResolver(new StringAndClassLoaderResourceResolver());
resolver.setPrefix("mail/"); // src/test/resources/mail
resolver.setSuffix(".html");
resolver.setTemplateMode("LEGACYHTML5");
resolver.setCharacterEncoding(CharEncoding.UTF_8);
resolver.setOrder(1);
templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(resolver);
}
@Test
public void testStringResolution() {
String expected = "<div>dave</div>";
String input = "<div th:text=\"${userName}\">Some Username Here!</div>";
IContext context = new StringAndClassLoaderResourceResolver.StringContext(input);
context.getVariables().put("userName", "dave");
String actual = templateEngine.process("redundant", context);
assertEquals(expected, actual);
}
@Test
public void testClasspathResolution(){
IContext context = new Context();
context.getVariables().put("message", "Hello Thymeleaf!");
String actual = templateEngine.process("dummy", context);
String expected = "<h1>Hello Thymeleaf!</h1>";
assertEquals(expected, actual);
}
}
src / main / resources / mail / dummy.html中的虚拟模板文件
<h1 th:text="${message}">A message will go here!</h1>
注意:我们使用Apache CommonsIO的 IOUtils 将String转换为InputStream
答案 1 :(得分:5)
您可以实施自己的TemplateResolver
和IResourceResolver
以使用String
。
答案 2 :(得分:4)
用于简单的单元测试:
static class TestResourceResolver implements IResourceResolver {
public String content = "";
@Override
public String getName() {
return "TestTemplateResolver";
}
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters templateProcessingParameters,
String resourceName) {
return new ByteArrayInputStream(content.getBytes());
}
}
或仅在Thymeleaf 3中使用org.thymeleaf.templateresolver.StringTemplateResolver
答案 3 :(得分:2)
是的,可以使用StringTemplateResolver。
public class ReportTemplateEngine {
private static TemplateEngine instance;
private ReportTemplateEngine() {}
public static TemplateEngine getInstance() {
if(instance == null){
synchronized (ReportTemplateEngine.class) {
if(instance == null) {
instance = new TemplateEngine();
StringTemplateResolver templateResolver = new StringTemplateResolver();
templateResolver.setTemplateMode(TemplateMode.HTML);
instance.setTemplateResolver(templateResolver);
}
}
}
return instance;
}
}