如何使用 Freemarker 变量解析字符串 HTML
How to parse String HTML with Freemarker variables
我正在从数据库中检索一个包含 HTML 和 Freemarker 语法混合的字符串值。
像这样:
<p>${fragment.title}</p>
<table id='resultsTable' class='material-table'>
<tr>
<th>Instruction</th>
<th>Action</th>
</tr>
Test
</table>
以下是我在Freemarker模板中访问上述字符串的方式:
<#include "inc/header.ftl">
<body>
<#include "inc/navigation.ftl">
<div class="container">
<div class="row">
<#if fragments??>
<#list fragments as fragment>
<div class="col-sm-6">
<div class="fragment">
${fragment.design?html}
</div>
</div>
</#list>
</#if>
</div>
</div>
</body>
<#include "inc/footer.ftl">
但是输出不太正确:
<p>${fragment.title}</p> <table id='resultsTable' class='material-table'> <tr> struction</th> </th> </tr> ddd </table>
如何使用Freemarker同时解析HTML和${fragment.title}
的值?
选项一:在java 控制器中处理您的字符串。这样你就不需要改变模板
@RequestMapping("/test2")
public ModelAndView test2() throws IOException, TemplateException {
Map<String, String> fragment = new HashMap<>();
fragment.put("title", "Some Title");
ModelAndView model = new ModelAndView("index", "fragment", fragment);
//your string should go here instead of this default
String template = "<div>${fragment.title}</div> <div>some other test</div>";
fragment.put("design", processTemplate(model.getModel(), template));
return model;
}
private String processTemplate(Map model, String template)
throws IOException, TemplateException {
Template t = new Template("TemplateFromDBName", template,
Environment.getCurrentEnvironment().getConfiguration());
Writer out = new StringWriter();
t.process(model, out);
return out.toString();
}
模板部分:
<div class="fragment">
${fragment.design}
</div>
选项二:创建可在模板中使用的自定义 method expression。
// http://freemarker.org/docs/pgui_datamodel_method.html
public static class ProcessString implements TemplateMethodModelEx {
public static final String PROCESS_STRING_FUNCTION_NAME = "processString";
public TemplateModel exec(List args) throws TemplateModelException {
if (args.size() != 1 ) throw new TemplateModelException("Wrong arguments");
try {
Environment env = Environment.getCurrentEnvironment();
Template t = new Template("TemplateFromDBName",
args.get(0).toString(), env.getConfiguration());
Writer out = new StringWriter();
t.process(env.getDataModel(), out);
return new SimpleScalar(out.toString());
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
return new SimpleScalar("");
}
}
在配置中注册
@Configuration
public class FreeMarkerConfig extends WebMvcConfigurerAdapter {
@Bean
@Primary
public FreeMarkerConfigurer freemarkerConfig( ) {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
// some other config here
Map properties = new HashMap();
properties.put(ProcessString.PROCESS_STRING_FUNCTION_NAME,
new ProcessString());
freeMarkerConfigurer.setFreemarkerVariables(properties);
return freeMarkerConfigurer;
}
}
模板将如下所示:
<div class="fragment">
${processString(fragment.design)}
</div>
但是控制器会很干净
@RequestMapping("/test")
public ModelAndView test() throws IOException, TemplateException {
Map<String, String> fragment = new HashMap<>();
fragment.put("title", "Some Title");
fragment.put("design", "<div>${fragment.title}</div><div> other test</div>");
return new ModelAndView("index", "fragment", fragment);
}
而不是 ${fragment.design?html}
,使用 <@fragment.design?interpret />
。
相关文档:
?interpret
: http://freemarker.org/docs/ref_builtins_expert.html#ref_builtin_interpret
?html
,你在这里不需要:
http://freemarker.org/docs/ref_builtins_string.html#ref_builtin_html
请注意,如果您需要每秒 运行 很多 ?interpret
-s,并且您倾向于在模板中一次又一次地解释相同的字符串,您可能需要一些自定义解决方案缓存并重用由这些字符串制成的 Template
-s。但是,在大多数应用程序中,?interpret
.
的性能不是问题
顺便说一句,如果您使用 <#list fragments! as fragment>
(请注意 !
),则不需要 #if fragments??
。
我正在从数据库中检索一个包含 HTML 和 Freemarker 语法混合的字符串值。
像这样:
<p>${fragment.title}</p>
<table id='resultsTable' class='material-table'>
<tr>
<th>Instruction</th>
<th>Action</th>
</tr>
Test
</table>
以下是我在Freemarker模板中访问上述字符串的方式:
<#include "inc/header.ftl">
<body>
<#include "inc/navigation.ftl">
<div class="container">
<div class="row">
<#if fragments??>
<#list fragments as fragment>
<div class="col-sm-6">
<div class="fragment">
${fragment.design?html}
</div>
</div>
</#list>
</#if>
</div>
</div>
</body>
<#include "inc/footer.ftl">
但是输出不太正确:
<p>${fragment.title}</p> <table id='resultsTable' class='material-table'> <tr> struction</th> </th> </tr> ddd </table>
如何使用Freemarker同时解析HTML和${fragment.title}
的值?
选项一:在java 控制器中处理您的字符串。这样你就不需要改变模板
@RequestMapping("/test2")
public ModelAndView test2() throws IOException, TemplateException {
Map<String, String> fragment = new HashMap<>();
fragment.put("title", "Some Title");
ModelAndView model = new ModelAndView("index", "fragment", fragment);
//your string should go here instead of this default
String template = "<div>${fragment.title}</div> <div>some other test</div>";
fragment.put("design", processTemplate(model.getModel(), template));
return model;
}
private String processTemplate(Map model, String template)
throws IOException, TemplateException {
Template t = new Template("TemplateFromDBName", template,
Environment.getCurrentEnvironment().getConfiguration());
Writer out = new StringWriter();
t.process(model, out);
return out.toString();
}
模板部分:
<div class="fragment">
${fragment.design}
</div>
选项二:创建可在模板中使用的自定义 method expression。
// http://freemarker.org/docs/pgui_datamodel_method.html
public static class ProcessString implements TemplateMethodModelEx {
public static final String PROCESS_STRING_FUNCTION_NAME = "processString";
public TemplateModel exec(List args) throws TemplateModelException {
if (args.size() != 1 ) throw new TemplateModelException("Wrong arguments");
try {
Environment env = Environment.getCurrentEnvironment();
Template t = new Template("TemplateFromDBName",
args.get(0).toString(), env.getConfiguration());
Writer out = new StringWriter();
t.process(env.getDataModel(), out);
return new SimpleScalar(out.toString());
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
return new SimpleScalar("");
}
}
在配置中注册
@Configuration
public class FreeMarkerConfig extends WebMvcConfigurerAdapter {
@Bean
@Primary
public FreeMarkerConfigurer freemarkerConfig( ) {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
// some other config here
Map properties = new HashMap();
properties.put(ProcessString.PROCESS_STRING_FUNCTION_NAME,
new ProcessString());
freeMarkerConfigurer.setFreemarkerVariables(properties);
return freeMarkerConfigurer;
}
}
模板将如下所示:
<div class="fragment">
${processString(fragment.design)}
</div>
但是控制器会很干净
@RequestMapping("/test")
public ModelAndView test() throws IOException, TemplateException {
Map<String, String> fragment = new HashMap<>();
fragment.put("title", "Some Title");
fragment.put("design", "<div>${fragment.title}</div><div> other test</div>");
return new ModelAndView("index", "fragment", fragment);
}
而不是 ${fragment.design?html}
,使用 <@fragment.design?interpret />
。
相关文档:
?interpret
: http://freemarker.org/docs/ref_builtins_expert.html#ref_builtin_interpret?html
,你在这里不需要: http://freemarker.org/docs/ref_builtins_string.html#ref_builtin_html
请注意,如果您需要每秒 运行 很多 ?interpret
-s,并且您倾向于在模板中一次又一次地解释相同的字符串,您可能需要一些自定义解决方案缓存并重用由这些字符串制成的 Template
-s。但是,在大多数应用程序中,?interpret
.
顺便说一句,如果您使用 <#list fragments! as fragment>
(请注意 !
),则不需要 #if fragments??
。