在我的 Spring Boot 应用程序中,我需要处理单个 Thymeleaf 片段以获得其渲染的 HTML 输出。
我正在注射
@Autowired
private SpringTemplateEngine templateEngine;
然后尝试
Context context = new Context();
context.setVariable("key", value);
String html = this.templateEngine.process("fragments/foo :: bar(key=${key})", context);
与
foo.html
位于 src/main/resources/templates/fragments
:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head></head>
<body>
...
<th:block th:fragment="bar(key)">
<!-- doing fancy stuff with key... -->
</th:block>
...
</body>
</html>
我没有更改 Thymeleaf 的任何自动配置值。
运行此代码,出现以下异常:
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "fragments/foo :: bar(key=${key})", template might not exist or might not be accessible by any of the configured Template Resolvers
at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:246) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:924) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:898) ~[thymeleaf-2.1.4.RELEASE.jar:2.1.4.RELEASE]
...
我在这里做错了什么吗?如果我创建一个仅包含内容的文件
src/main/resources/templates/fragments/test.html
,那么整个事情就会开始工作
<div th:replace="fragments/foo :: bar(key=${key})"></div>
并通过
处理它String html = this.templateEngine.process("fragments/test", context);
这将是一个可能的解决方案,但对我来说似乎有点黑客......
肯的答案有效,但我用更简单的方式做到了:
templateEngine.process("nameTemplate", context, new DOMSelectorFragmentSpec("DOM selector"));
还有其他方法可以过滤处理后的模板,记录在这里
SpringTemplateEngine
不解析片段。因此,模板名称不应包含片段声明。要处理片段,您必须使用另一个重载的 SpringTemplateEngine.process()
方法,并手动解析片段:
Context context = new Context();
context.setVariable("key", value);
ProcessingContext processingContext = new ProcessingContext(context);
StandardFragment fragmentSpec =
StandardFragmentProcessor.computeStandardFragmentSpec(templateEngine.getConfiguration(),
processingContext, "fragments/foo :: #bar", "SpringStandard", "fragment");
String html = templateEngine.process("fragments/foo",
context, fragmentSpec.getFragmentSpec());
实际上,我没有使用
<th:block>
作为片段。我的片段如下所示:
<body>
...
<div id="bar" th:remove="tag">
<!-- doing fancy stuff with key... -->
<span th:text="${key}"></span>
</div>
...
</body>
正如您所指出的,我通过
#bar
div 的 id 选择了这个片段。
使用 Thymeleaf 3.0.6 这非常简单。我没有找到直接的答案,所以我附上我的答案。 我有一个包含片段的文件(
myFragments.html
):
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="firstFragment">
<p th:text="${message}"></p>
</div>
<div th:fragment="secondFragment">
<p th:text="${message}"></p>
</div>
</html>
我可以使用这个片段在 Java 代码中生成 HTML 输出,如下所示:
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.util.Set;
@Service
public ContentBuildService {
@Autowired
private TemplateEngine templateEngine;
private String buildContent(String myMessage) {
Context context = new Context();
context.setVariable("message", myMessage);
Set<String> fragmentsSelectors =
Sets.newHashSet("firstFragment");
return templateEngine.process("myFragments",fragmentsSelectors, context);
}
}
我正在使用 Guava 库来创建 HashSet,但您当然可以创建简单的
new HashSet()
并添加具有片段名称的元素。
我在 Thymeleaf 3 中为这个问题苦苦挣扎了一段时间,在搜索时找不到任何答案。对于遇到此问题的其他人,它在 TL 3 中进行了更改。现在您使用
Set<String>
参数,该参数没有在任何地方记录,但工作原理如下:
final Set<String> params = new HashSet<>();
params.add("/dashboard-fragment");
params.add("list");
final String result = engine.process("/dashboard-fragment", params, context);
这相当于使用
/dashboard-fragment :: list
片段规范。有效!
当 Java 9 最终发布时,我想您可以使用
Set.of()
工厂方法将其减少为一行。
我使用的是Spring 3.2.0。上面的答案,尤其是
user2959589
帮助我做出了以下内容:
private final SpringTemplateEngine templateEngine;
private String renderFragment(String templateName, String fragmentName, ModelMap model) {
Context context = new Context();
context.setVariables(model);
final Set<String> params = new HashSet<>();
// params.add(templateName);
params.add(fragmentName);
return templateEngine.process(templateName, params, context);
}
请注意,
params.add(templateName)
已被注释掉 - 对我来说,它是否存在没有任何区别。
此代码还允许您向下传递模型,您不需要将参数添加到片段名称中(例如:
fragment/block :: myFragment(...)
)
这样称呼:
ModelMap model = new ModelMap();
model.addAttribute("fragmentVars", "vars");
String html = renderFragment("/fragments/blocks", "myFragment", model);
我想你可以修改 renderFragment 以获取未更改的
/fragments/block :: myFragment
并将正确的部分放置在正确的位置,但这已经是我需要的了。