Java 从数据库加载FreeMarker模板
我想将我的FreeMarker模板存储在一个数据库表中,该表类似于:Java 从数据库加载FreeMarker模板,java,templates,freemarker,Java,Templates,Freemarker,我想将我的FreeMarker模板存储在一个数据库表中,该表类似于: template_name | template_content --------------------------------- hello |Hello ${user} goodbye |So long ${user} 当收到对具有特定名称的模板的请求时,这将导致执行查询,从而加载相关模板内容。该模板内容以及数据模型(上述示例中“user”变量的值)应传递给FreeMarker 但是,似乎假
template_name | template_content
---------------------------------
hello |Hello ${user}
goodbye |So long ${user}
当收到对具有特定名称的模板的请求时,这将导致执行查询,从而加载相关模板内容。该模板内容以及数据模型(上述示例中“user”变量的值)应传递给FreeMarker
但是,似乎假定每个模板名对应于文件系统特定目录中的同名文件。是否有任何方法可以轻松地从DB而不是文件系统加载模板
编辑:我应该提到,我希望能够在应用程序运行时将模板添加到数据库中,因此我不能简单地在启动时将所有模板加载到新的StringTemplateLoader中(如下所示)。有几种方法:
- 创建的新实现以直接从数据库加载模板,并在加载任何模板之前使用
将其传递给实例setTemplateLoader()
- 使用应用程序启动时从数据库配置的。如上所述,将其添加到配置中
编辑根据提问者的编辑,您自己的TemplateLoader实现看起来是一个不错的选择。查看Javadoc,它是一个简单的小接口,只有四种方法,其行为有很好的文档记录。我们使用StringTemplateLoader来加载我们从db获得的Tempate(正如Dan Vinton所建议的) 以下是一个例子:
StringTemplateLoader stringLoader = new StringTemplateLoader();
String firstTemplate = "firstTemplate";
stringLoader.putTemplate(firstTemplate, freemarkerTemplate);
// It's possible to add more than one template (they might include each other)
// String secondTemplate = "<#include \"greetTemplate\"><@greet/> World!";
// stringLoader.putTemplate("greetTemplate", secondTemplate);
Configuration cfg = new Configuration();
cfg.setTemplateLoader(stringLoader);
Template template = cfg.getTemplate(firstTemplate);
StringTemplateLoader stringLoader=新StringTemplateLoader();
字符串firstTemplate=“firstTemplate”;
stringLoader.PuttTemplate(第一个模板,freemarkerTemplate);
//可以添加多个模板(它们可能相互包含)
//String secondTemplate=“World!”;
//stringLoader.PuttTemplate(“greetTemplate”,第二个模板);
Configuration cfg=新配置();
cfg.setTemplateLoader(stringLoader);
模板模板=cfg.getTemplate(firstTemplate);
编辑
您不必在启动时加载所有模板。无论何时访问模板,我们都会从数据库中获取它,并通过StringLoader加载它,并通过调用template.process()生成(在本例中)XML输出。自2.3.20以来,您只需:
这是一个方便的构造函数。对于那些寻找一些代码的人来说,它就在这里。请查看代码中的注释,以便更好地理解 数据库模板:
@Entity
public class DBTemplate implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private long templateId;
private String content; // Here's where the we store the template
private LocalDateTime modifiedOn;
}
TemplateLoader实现(EMF是EntityManagerFactory的实例):
最后,使用它:
...
long someId = 3L;
Template template = templateConfig.getTemplate("" + someId);
...
这非常有效,允许您使用Freemarker的所有功能,如导入、包含等。请看以下示例:
<#import "1" as layout> <!-- Use a template id. -->
<@layout.mainLayout>
...
...
或在:
<#include "3"> <!-- Use a template id. -->
...
...
我在自己的CMS(肉桂框架)上使用这个加载程序,工作起来很有魅力
最好,实施配置 例如:
@Configuraton
public class FreemarkerConfig {
@Autowired
TemplateRepository tempRepo;
@Autowired
TemplateUtils tempUtils;
@Primary
@Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
// Create new configuration bean
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
// Create template loader
StringTemplateLoader sTempLoader = new StringTemplateLoader();
// Find all templates
Iterable<TemplateDb> ite = tempRepo.findAll();
ite.forEach((template) -> {
// Put them in loader
sTempLoader.putTemplate(template.getFilename(), template.getContent());
});
// Set loader
bean.setPreTemplateLoaders(sTempLoader);
return bean;
}
老问题,但对于任何有相同问题的人,我实现了一个简单的解决方案,无需自定义模板加载器或在启动时加载模板 假设数据库中有动态模板: 数据库:
你好${params.user}
您只需创建一个Freemarker文件(ftlh),该文件解释接收到的字符串(内容
),并使用以下命令从中生成模板:
dynamic.ftlh:
然后,在java代码中,您只需要从数据库中获取字符串(就像从数据库中检索任何其他数据一样),并使用具有exploration
的文件来生成模板:
爪哇:
String content=getFromDatabase();
Configuration cfg=getConfiguration();
字符串filePath=“dynamic.ftlh”;
Map params=新的HashMap();
参数put(“用户”、“世界”);
Map root=newhashmap();
root.put(“内容”,content);
root.put(“params”,params);
Template-Template=cfg.getTemplate(文件路径);
尝试(Writer out=new StringWriter()){
模板。进程(根,出);
字符串结果=out.toString();
系统输出打印项次(结果);
}
(将方法getFromDatabase()
和getConfiguration()
分别更改为希望从数据库获取动态内容和获取动态内容的任何方法)
应打印:
你好,世界
然后,您可以更改数据库中的动态内容或创建其他内容、添加新参数等,而无需创建其他Freemarker文件(ftlh)。我认为您可以设置Configuration.setLocalizedLookup(布尔)以禁用本地化查找,这样您就不必捕获NumberFormatException。
<#import "1" as layout> <!-- Use a template id. -->
<@layout.mainLayout>
...
<#include "3"> <!-- Use a template id. -->
...
@Configuraton
public class FreemarkerConfig {
@Autowired
TemplateRepository tempRepo;
@Autowired
TemplateUtils tempUtils;
@Primary
@Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
// Create new configuration bean
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
// Create template loader
StringTemplateLoader sTempLoader = new StringTemplateLoader();
// Find all templates
Iterable<TemplateDb> ite = tempRepo.findAll();
ite.forEach((template) -> {
// Put them in loader
sTempLoader.putTemplate(template.getFilename(), template.getContent());
});
// Set loader
bean.setPreTemplateLoaders(sTempLoader);
return bean;
}
@Autowired
private Configuration freemarkerConfig;
Template template = freemarkerConfig.getTemplate(templateFilePath);
String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, mapTemplate);