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

如何提取Groovy DSL构建器片段复用并保留IDE自动补全?

问题:复用Groovy DSL构建器中的部分内容

是否有可行方法将Groovy DSL构建器的部分内容提取为变量或辅助函数,以便实现复用?以下是用于声明邮件的构建器风格Groovy DSL极简示例:

email {
    from("pepa@depo.cz")
    to("lojza@depo.cz")
    body {
        html("Ahoj")
        // 更多字段定义
    }
}

希望提取其中的body部分:

body {
    html("Ahoj")
    // 更多字段定义
}

并在多封邮件中复用,理想效果如下:

email {
    from("pepa@depo.cz")
    to("lojza@depo.cz")
    myBody("Ahoj1")
}

email {
    from("pepa@depo.cz")
    to("lojza@depo.cz")
    myBody("Ahoj2")
}

同时需要保留myBody函数的IDE自动补全功能。

以下是自包含的DSL实现代码:

/// 简化的DSL示例
def email(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = EmailSpec) Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

class EmailSpec {
    void from(String from) { println "From: $from" }
    void to(String... to) { println "To: $to" }

    void body(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = BodySpec) Closure body) {
        def bodySpec = new BodySpec()
        def code = body.rehydrate(bodySpec, this, this)
        code.resolveStrategy = Closure.DELEGATE_ONLY
        code()
    }
}

class BodySpec {
    void html(String html) { println "Body (html): $html" }
}

注:上述DSL仅用于示例,实际需要在Jenkins Job DSL中实现相同操作。


解决方案

方法1:扩展Spec类添加复用方法(推荐,保障IDE补全)

直接在EmailSpec类中新增myBody方法,内部调用原有的body逻辑并封装重复配置。由于方法属于EmailSpec类,且email闭包通过@DelegatesTo指定了委托类型,IDE会自动识别并提供补全。

修改后的完整代码:

def email(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = EmailSpec) Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

class EmailSpec {
    void from(String from) { println "From: $from" }
    void to(String... to) { println "To: $to" }

    void body(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = BodySpec) Closure body) {
        def bodySpec = new BodySpec()
        def code = body.rehydrate(bodySpec, this, this)
        code.resolveStrategy = Closure.DELEGATE_ONLY
        code()
    }

    // 新增复用方法,支持传入动态参数
    void myBody(String content) {
        body {
            html(content)
            // 这里可以添加固定的body配置,比如默认文本、附件等
            // text("默认文本内容")
        }
    }
}

class BodySpec {
    void html(String html) { println "Body (html): $html" }
}

调用时直接使用myBody("Ahoj1")即可,完全符合你的理想效果,且IDE能正常补全该方法。

方法2:使用闭包变量复用(灵活场景)

如果需要更灵活的复用(比如不同场景下的body配置变体),可以定义带参数的闭包变量,通过curry绑定参数后传入body方法。为了让IDE识别闭包内的可用方法,需添加@DelegatesTo注解指定委托类型。

示例代码:

// 定义复用的body闭包,指定委托类型为BodySpec
@DelegatesTo(value = BodySpec, strategy = Closure.DELEGATE_ONLY)
Closure myBody = { String content ->
    html(content)
    // 其他固定配置
}

// 调用时通过curry绑定动态参数
email {
    from("pepa@depo.cz")
    to("lojza@depo.cz")
    body(myBody.curry("Ahoj1"))
}

email {
    from("pepa@depo.cz")
    to("lojza@depo.cz")
    body(myBody.curry("Ahoj2"))
}

这种方式适合需要在多个DSL上下文复用同一段配置的场景,IDE也能识别闭包内的html等方法。

Jenkins Job DSL适配提示

Jenkins Job DSL基于Groovy,核心思路完全一致:

  • 若为自定义DSL扩展,直接在对应的Spec类中添加复用方法;
  • 若为Jenkins内置DSL(如邮件通知、构建步骤),可定义全局辅助闭包并通过@DelegatesTo指定对应上下文类型,保障IDE补全。

示例(Jenkins邮件通知复用):

// 定义复用的邮件body闭包,指定委托类型为Jenkins的BodyContext
@DelegatesTo(value = BodyContext, strategy = Closure.DELEGATE_ONLY)
Closure customMailBody = { String subject ->
    html """
        <h3>${subject}</h3>
        <p>构建详情:<a href="${BUILD_URL}">点击查看</a></p>
    """
}

// 在Job配置中复用
job('demo-job') {
    publishers {
        mailer {
            recipients('team@example.com')
            body(customMailBody.curry('构建成功通知'))
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:21:06