You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用Groovy的MarkupTemplateEngine渲染MJML模板?求可行示例

用Groovy的MarkupTemplateEngine渲染MJML模板是否可行?

可行,但你的代码问题出在MJML标签的连字符解析上:Groovy会把mj-text()这类带连字符的写法解析成mj - text()(变量mj减去变量text),导致空指针异常(因为mj变量不存在)。

你的当前实现代码:

import groovy.text.markup.*

String mjmlTemplate = '''
mjml {
    mj-head {
        mj-title('Hello World')
        mj-preview('This is a preview text')
    }
    mj-body {
        mj-section {
            mj-column {
                mj-text('Hello World from MJML')
            }
        }
    }
}
'''

TemplateConfiguration config = new TemplateConfiguration();
MarkupTemplateEngine engine = new MarkupTemplateEngine(config);

def template = engine.createTemplate(mjmlTemplate)
def renderedMJML = template.make().toString()

println renderedMJML

运行报错:

Caught: java.lang.NullPointerException: Cannot invoke method minus() on null object
java.lang.NullPointerException: Cannot invoke method minus() on null object
        at GeneratedMarkupTemplate0$_run_closure1$_closure2.doCall(GeneratedMarkupTemplate0:4)
        at GeneratedMarkupTemplate0$_run_closure1$_closure2.doCall(GeneratedMarkupTemplate0)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at GeneratedMarkupTemplate0$_run_closure1.doCall(GeneratedMarkupTemplate0:3)
        at GeneratedMarkupTemplate0$_run_closure1.doCall(GeneratedMarkupTemplate0)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at GeneratedMarkupTemplate0.run(GeneratedMarkupTemplate0:2)
        at test.run(test.groovy:30)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)

可运行的修正示例:

核心是把带连字符的MJML标签用字符串方法调用,避免Groovy解析错误,同时禁用HTML转义确保MJML格式正确:

import groovy.text.markup.*

String mjmlTemplate = '''
// 用字符串形式调用带连字符的标签
"mjml" {
    "mj-head" {
        "mj-title"('Hello World')
        "mj-preview"('This is a preview text')
    }
    "mj-body" {
        "mj-section" {
            "mj-column" {
                "mj-text"('Hello World from MJML')
            }
        }
    }
}
'''

TemplateConfiguration config = new TemplateConfiguration()
// 禁用HTML转义,防止MJML标签被转义
config.setEscapeHtml(false)
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)

def template = engine.createTemplate(mjmlTemplate)
def renderedMJML = template.make().toString()

println renderedMJML

输出结果:

<mjml>
  <mj-head>
    <mj-title>Hello World</mj-title>
    <mj-preview>This is a preview text</mj-preview>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text>Hello World from MJML</mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

关键说明:

  1. 用"mj-tag-name"()的形式调用标签,避免Groovy把连字符解析成减法运算符
  2. 配置setEscapeHtml(false)防止MJML的特殊字符被转义,确保生成的MJML格式可被后续MJML处理器正常解析

内容的提问来源于stack exchange,提问作者Grace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:23:26