【问题标题】:Freemarker get original template objectFreemarker 获取原始模板对象
【发布时间】:2018-01-22 11:29:07
【问题描述】:

我正在使用 Spring Boot 和 Freemarker。我正在使用自定义加载器从 db 加载我的模板:

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;

如您所见,我返回了一个来自 db 的 MyTemplate 对象。当我得到自定义模板来处理文本时,我会这样做:

contentFreemarkerConfig.getTemplate(CommunicationType.WALLET_BALANCE_THRESHOLD + "|" + Channel.EMAIL, locale)

但是这一行返回一个freemarker.template.Template。我想拿回我原来的模板,以避免在 db 上进行另一个查询来获取它。

Freemarker 可以做到吗?

【问题讨论】:

  • 由于TemplateLoader 用于加载原始源(字符流),而不是用于创建Template 对象,当然它不适用于这种方法。我也不知道MyTemplate 中有什么。 (将电子邮件地址附加到模板名称也是可疑的,因为它会导致缓存膨胀。)更高级别的目标是什么?
  • @ddekany MyTemplate 有内容、发件人和主题。我需要发送电子邮件的所有事情。如果是模板类型,我不会将电子邮件地址附加到名称 Channel.EMAIL 中。我也有 Channel.SMS。就这样。所以缓存被保存了 ;-) 拥有我的对象的重点是读取其他信息而不需要进行其他查询。
  • MyTemplate.contentsendersubjects 是否像模板本身?如果是这样,传统的解决方案实际上是创建 3 个模板("wallet_blance_email_content.ftlh""wallet_balance_earth_subject.ftl" 等)。没有“批量加载”功能,尽管模板缓存应该主要屏蔽开销。
  • @ddekany 我将我的 bean 添加到问题中以澄清。我是这么想的。我已经为内容和主题这样做了,但我认为对发件人或我需要的其他属性也这样做很奇怪。确实模板在缓存中,但以编程方式加载 3 个不同的模板很奇怪。更奇怪的是,“发件人”不应该被处理。谢谢

标签: java spring-boot freemarker


【解决方案1】:

您在这里尝试做的(如果我理解得很好)是让 FreeMarker 为您缓存应用程序域对象。这不是标准模板加载/缓存机制的设计目的;模板库是一个较低级别的层,仅处理其 FreeMarker Template-s。由于每个域对象需要多个 Template-s,您甚至不能将其与 Template.customAttributes 和自定义 TemplateConfigurerFactory (可用于基于 @ 将任意对象附加到 Template-s 987654326@)。所以,我认为你应该做的是:

  • 使用任何专用的缓存解决方案来缓存您的域对象。域对象可以直接存储 Template 对象(在您的情况下是多个)。当您为缓存未命中创建域对象时,只需使用 Template 构造函数创建那些 Template 对象。因此对于那些Template-s FreeMarker 的TemplateLoader 和缓存没有使用。只要它们不需要#include#import 彼此(因此 FreeMarker 需要能够获取它们),那很好。

  • 为了上述模板需要#include#import(即常用实用程序模板)的模板,设置一个TemplateLoader和FreeMarker的缓存将用于它们。由于这些只是模板,而不是某些应用程序域对象,因此您当然不需要做任何棘手的事情。 (此外,此类模板通常存储在类路径资源或配置目录中,因此您甚至不需要DatabaseTemplateLoader。)

【讨论】:

    猜你喜欢
    • 2021-04-15
    • 2015-11-19
    • 2011-01-18
    • 2021-12-16
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    相关资源
    最近更新 更多