【问题标题】:Use FreeMarker Template in Spring Boot with nested XML template在 Spring Boot 中使用带有嵌套 XML 模板的 FreeMarker 模板
【发布时间】:2018-09-06 14:35:51
【问题描述】:

所以我有下面的 FreeMarker 模板:

<?xml version="1.0" encoding="ISO-8859-1"?>
<master>
    <header>
        <version>${version}</version>
        <created>${created}</created>
        <creator>${creator}</creator>
        <draw>${draw}</draw>
        <game>${game}</game>
        <type>${type}</type>
        <sender>${sender}</sender>
        <recipient>${recipient}</recipient>
        <revision>${revision}</revision>
    </header>
    <data>
        <stake>
        ${stake}
        </stake>
        <checksum_combifile>
        ${checksumFile}
        </checksum_combifile>
    </data>
</master>

以及下面的用于 FreeMarker 模板的 POJO:

public class SscMessageVo {

    /* Header */
    private String version = "1.00";
    private String created;
    private String creator;
    private String draw;
    private String game;
    private String type;
    private String sender;
    private String recipient;
    private String revision;

    /* Data */
    private String stake;
    private String checksumFile;

    public SscMessageVo() {
        super();
    }

    public SscMessageVo(final String version, final String created, final String creator, final String draw, final String game, final String type, final String sender, final String recipient,
        final String revision, final String stake, final String checksumFile) {
        super();
        this.version = version;
        this.created = created;
        this.creator = creator;
        this.draw = draw;
        this.game = game;
        this.type = type;
        this.sender = sender;
        this.recipient = recipient;
        this.revision = revision;
        this.stake = stake;
        this.checksumFile = checksumFile;
    }

    public String getStake() {

        return stake;
    }

    public void setStake(final String stake) {

        this.stake = stake;
    }

    public String getChecksumFile() {

        return checksumFile;
    }

    public void setChecksumFile(final String checksumFile) {

        this.checksumFile = checksumFile;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(final String version) {
        this.version = version;
    }

    public String getCreated() {
        return created;
    }

    public void setCreated(final String created) {
        this.created = created;
    }

    public String getCreator() {
        return creator;
    }

    public void setCreator(final String creator) {
        this.creator = creator;
    }

    public String getDraw() {
        return draw;
    }

    public void setDraw(final String draw) {
        this.draw = draw;
    }

    public String getGame() {
        return game;
    }

    public void setGame(final String game) {
        this.game = game;
    }

    public String getType() {
        return type;
    }

    public void setType(final String type) {
        this.type = type;
    }

    public String getSender() {
        return sender;
    }

    public void setSender(final String sender) {
        this.sender = sender;
    }

    public String getRecipient() {
        return recipient;
    }

    public void setRecipient(final String recipient) {
        this.recipient = recipient;
    }

    public String getRevision() {
        return revision;
    }

    public void setRevision(final String revision) {
        this.revision = revision;
    }

}

一切都好,甜蜜而快乐,但现在我想做下面的事情,避免重复,因为我有许多具有相同标题结构的模板,将属于标题的变量移动到一个名为 TemplateHeader 的新类强>,像这样:

public class TemplateHeader {

    /* Header */
    private String version;
    private String created;
    private String creator;
    private String draw;
    private String game;
    private String type;
    private String sender;
    private String recipient;
    private String revision;

    public TemplateHeader() {
        super();
    }

    public TemplateHeader(String version, String created, String creator, String draw, String game, String type, String sender, String recipient, String revision) {
        super();
        this.version = version;
        this.created = created;
        this.creator = creator;
        this.draw = draw;
        this.game = game;
        this.type = type;
        this.sender = sender;
        this.recipient = recipient;
        this.revision = revision;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getCreated() {
        return created;
    }

    public void setCreated(String created) {
        this.created = created;
    }

    public String getCreator() {
        return creator;
    }

    public void setCreator(String creator) {
        this.creator = creator;
    }

    public String getDraw() {
        return draw;
    }

    public void setDraw(String draw) {
        this.draw = draw;
    }

    public String getGame() {
        return game;
    }

    public void setGame(String game) {
        this.game = game;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getSender() {
        return sender;
    }

    public void setSender(String sender) {
        this.sender = sender;
    }

    public String getRecipient() {
        return recipient;
    }

    public void setRecipient(String recipient) {
        this.recipient = recipient;
    }

    public String getRevision() {
        return revision;
    }

    public void setRevision(String revision) {
        this.revision = revision;
    }

}

但我不知道该怎么做,我从 FreeTemplate 收到错误,并且在网上找不到任何教程....

【问题讨论】:

  • 不清楚你在分离标题字段后尝试了什么。数据模型(模板上下文)看起来如何?你期望什么,你得到了什么错误?
  • @ddekany 模板完全一样。我只想在另一个类上分离标题值:)
  • 所以你想使用组合而不是继承 (SscMessageVo extends TemplateHeader),这在 Java API 中是不透明的,但你希望它对模板是透明的?就 FreeMarker 而言,这是可能的,您只需要创建一个自定义的 TemplateHashModel 实现,该实现委托给另外两个 TemplateHashModel-s(到 config.getObjectWrapper().wrap(...)-ed 标头 bean,以及类似包装的非标头 bean )。除非 Spring 本身支持从两个 bean 的联合创建模型。
  • @ddekany 好吧,如果我扩展 TemplateHeader,它会真正起作用吗?
  • @ddekany 请你发布一个答案我会接受它♡

标签: java spring spring-boot freemarker


【解决方案1】:

您可以使用继承(SscMessageVo 扩展TemplateHeader)。请注意,类和 getter 方法都必须是公共的。

如果您想使用组合,如果它在 Java API 中不透明(如在myComposite.getHeader().getCreator() 中),那就更棘手了。但它可以在模板中是透明的。 更新:只需创建您的数据模型,如 TemplateModelUtils.wrapAsHashUnion(config.getObjectWrapper(), myHeader, myData),其中myHeadermyData 是您要“组合”的对象。

但是,TemplateModelUtils.wrapAsHashUnion 仅存在于 2.3.29 之后(远未在 2018-09-12 发布)。所以同时,检查源代码(https://github.com/apache/freemarker/blob/2.3-gae/src/main/java/freemarker/template/utility/TemplateModelUtils.java)。不过,您的可能要简单得多。你只需要像var ow = cfg.getObjectWrapper(); TemplateHashModel dataModel = new HashUnionModel(ow.wrap(myHeader), ow.wrap(myData)); 这样的东西,然后使用dataModel 作为你的数据模型。

【讨论】:

  • 我将使用你的第一段继承......虽然我想看看另一段描述的解决方案的一些代码,因为我什么都不懂:)。然后我会很高兴地接受你的回答:)
  • 请给我一些作曲代码?我真的很难理解它:'(
  • 由于其他一些用户太早需要这个,我决定为此向 FreeMarker 2.3.29 添加一个实用程序。请参阅我的评论。
  • 对不起,我在答案末尾的示例代码遗漏了一些片段......现在看。正如您将看到的,您只需要复制HashUnionModel(2.3.29 之前),这是一个相当简单的类。 (另外,不,我不是 FreeMarker 的原作者,尽管我已经做了很长一段时间的大部分维护工作。)
  • @GOXR3PLUS 在 12 月下旬应该有一个......理想情况下。不知道你在找什么,因为你已经按照你说的那样使用我的课程了。
猜你喜欢
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2015-05-19
  • 1970-01-01
  • 2015-06-01
  • 2016-07-19
  • 2021-11-27
相关资源
最近更新 更多