Freemarker 获取原始模板对象
Freemarker get original template object
我正在使用 Spring Boot 和 Freemarker。我正在使用自定义加载程序从数据库加载我的模板:
public class ContentDbLoader implements TemplateLoader {
@Inject
private TemplateRepository templateRepository;
@Override
public void closeTemplateSource(Object templateSource) throws IOException {
return;
}
@Override
public Object findTemplateSource(String name) throws IOException {
return getTemplateFromName(name);
}
@Override
public long getLastModified(Object templateSource) {
MyTemplate template = (MyTemplate) templateSource;
template = templateRepository.findOne(template.getId());
return template.getLastModifiedDate().toEpochMilli();
}
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
return new StringReader(((Template) templateSource).getContent());
}
private MyTemplate getTemplateFromName(String name) {
//my logic
}
}
我的模型是:
Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "channel", "communicationType", "country_id" }) })
public class Template extends AbstractEntity {
private static final long serialVersionUID = 8405971325717828643L;
@NotNull
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Channel channel;
@NotNull
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private CommunicationType communicationType;
@Size(max = 255)
private String subject;
@NotNull
@Column(nullable = false)
@Lob
private String content;
@NotNull
@Column(nullable = false)
private String sender;
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Country country;
如您所见,我 return 一个来自数据库的 MyTemplate 对象。当我获得自定义模板来处理文本时,我会这样做:
contentFreemarkerConfig.getTemplate(CommunicationType.WALLET_BALANCE_THRESHOLD + "|" + Channel.EMAIL, locale)
但是这一行 return 一个 freemarker.template.Template
。我想找回我的原始模板,以避免再次查询数据库来获取它。
Freemarker 可以吗?
你在这里尝试做的(如果我理解得很好的话)是让 FreeMarker 为你缓存应用程序域对象。这不是标准模板 loading/caching 机制的设计目的;模板库是一个较低级别的层,仅处理其 FreeMarker Template
-s。由于每个域对象需要多个 Template
-s,因此您甚至不能将其与 Template.customAttributes
和自定义 TemplateConfigurerFactory
(可用于将任意对象附加到 Template
-s 基于 templateSource
)。所以,我认为你应该做的是:
使用任何专用的缓存解决方案来缓存您的域对象。域对象可以直接存储 Template
个对象(在您的情况下是多个)。当您为缓存未命中创建域对象时,只需使用 Template
构造函数创建那些 Template
对象。因此对于那些 Template
-s FreeMarker 的 TemplateLoader
和缓存没有被使用。只要它们不需要 #include
或 #import
彼此(因此 FreeMarker 需要能够获得它们),那很好。
为了上述模板需要#include
或#import
的模板(即常用实用模板),设置一个TemplateLoader
和FreeMarker的缓存将用于它们。由于这些只是模板,而不是某些应用程序域对象,因此您当然不需要做任何棘手的事情。 (此外,此类模板通常存储在类路径资源或配置目录中,因此您甚至可能不需要 DatabaseTemplateLoader
。)
我正在使用 Spring Boot 和 Freemarker。我正在使用自定义加载程序从数据库加载我的模板:
public class ContentDbLoader implements TemplateLoader {
@Inject
private TemplateRepository templateRepository;
@Override
public void closeTemplateSource(Object templateSource) throws IOException {
return;
}
@Override
public Object findTemplateSource(String name) throws IOException {
return getTemplateFromName(name);
}
@Override
public long getLastModified(Object templateSource) {
MyTemplate template = (MyTemplate) templateSource;
template = templateRepository.findOne(template.getId());
return template.getLastModifiedDate().toEpochMilli();
}
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
return new StringReader(((Template) templateSource).getContent());
}
private MyTemplate getTemplateFromName(String name) {
//my logic
}
}
我的模型是:
Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "channel", "communicationType", "country_id" }) })
public class Template extends AbstractEntity {
private static final long serialVersionUID = 8405971325717828643L;
@NotNull
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Channel channel;
@NotNull
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private CommunicationType communicationType;
@Size(max = 255)
private String subject;
@NotNull
@Column(nullable = false)
@Lob
private String content;
@NotNull
@Column(nullable = false)
private String sender;
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Country country;
如您所见,我 return 一个来自数据库的 MyTemplate 对象。当我获得自定义模板来处理文本时,我会这样做:
contentFreemarkerConfig.getTemplate(CommunicationType.WALLET_BALANCE_THRESHOLD + "|" + Channel.EMAIL, locale)
但是这一行 return 一个 freemarker.template.Template
。我想找回我的原始模板,以避免再次查询数据库来获取它。
Freemarker 可以吗?
你在这里尝试做的(如果我理解得很好的话)是让 FreeMarker 为你缓存应用程序域对象。这不是标准模板 loading/caching 机制的设计目的;模板库是一个较低级别的层,仅处理其 FreeMarker Template
-s。由于每个域对象需要多个 Template
-s,因此您甚至不能将其与 Template.customAttributes
和自定义 TemplateConfigurerFactory
(可用于将任意对象附加到 Template
-s 基于 templateSource
)。所以,我认为你应该做的是:
使用任何专用的缓存解决方案来缓存您的域对象。域对象可以直接存储
Template
个对象(在您的情况下是多个)。当您为缓存未命中创建域对象时,只需使用Template
构造函数创建那些Template
对象。因此对于那些Template
-s FreeMarker 的TemplateLoader
和缓存没有被使用。只要它们不需要#include
或#import
彼此(因此 FreeMarker 需要能够获得它们),那很好。为了上述模板需要
#include
或#import
的模板(即常用实用模板),设置一个TemplateLoader
和FreeMarker的缓存将用于它们。由于这些只是模板,而不是某些应用程序域对象,因此您当然不需要做任何棘手的事情。 (此外,此类模板通常存储在类路径资源或配置目录中,因此您甚至可能不需要DatabaseTemplateLoader
。)