如何同时实现Groovy字符串的有序参数插值与嵌套子串?
Groovy Jenkins流水线:实现带有序参数的嵌套邮件模板
针对你用Groovy开发Jenkins流水线时,需要实现支持有序参数+字符串嵌套的邮件模板需求,这里整理了可行的解决思路,先明确你的需求和遇到的问题:
需求目标
希望打造可嵌套的邮件模板,同时支持有序参数填充,期望的模板结构如下:
// 任务中止/提前结束时使用的短模板 def shortEmail = """|Title: %1$s |Link: %2$s etc. """ // 任务正常完成时使用的长模板,嵌套短模板内容 def longEmail = """|${shortEmail} | |Build Results: %3$s |Test Results: %4$s etc. """
你遇到的问题
方案1:sprintf+有序参数
逻辑上最贴合需求,但在GString(三重双引号字符串)中使用%1$s这类有序参数时,Groovy会把%1当作变量解析,直接抛出MissingPropertyException异常。
方案2:SimpleTemplateEngine
支持通过绑定指定参数顺序,但无法直接实现模板嵌套;如果用GString嵌套shortEmail变量,初始化时${}中未定义的变量会直接触发MissingPropertyException异常,示例代码如下:
def longEmail = """|${shortEmail} | |# 以下绑定会触发错误 |Build Results: ${BUILD_RESULTS} |Test Results: ${TEST_RESULTS} etc. """
可行解决方案
方法1:普通字符串+sprintf分步格式化
把模板都定义为单引号包裹的普通字符串(避免GString提前解析),先格式化子模板,再代入父模板,完美保留有序参数和嵌套逻辑:
// 单引号定义普通字符串,避免Groovy提前解析%1$s def shortEmail = '''Title: %1$s Link: %2$s etc.''' // 长模板用%s占位符接收短模板的格式化结果,后续参数继续用有序占位符 def longEmailTemplate = '''%s Build Results: %1$s Test Results: %2$s etc.''' // 使用时分步格式化:先处理短模板,再传入长模板 def formattedShort = sprintf(shortEmail, ['任务中止通知', 'https://jenkins.example.com/job/xxx/123']) def formattedLong = sprintf(longEmailTemplate, [formattedShort, '构建成功', '测试通过率95%']) // 输出最终邮件内容 println(formattedLong)
方法2:SimpleTemplateEngine+模板拼接
先预编译子模板,父模板中预留子模板内容的占位符,最后统一绑定参数生成最终邮件:
import groovy.text.SimpleTemplateEngine def engine = new SimpleTemplateEngine() // 预编译短模板 def shortTemplate = engine.createTemplate('''Title: ${title} Link: ${link} etc.''') // 预编译长模板,用${shortContent}占位符接收短模板的内容 def longTemplate = engine.createTemplate('''${shortContent} Build Results: ${buildResult} Test Results: ${testResult} etc.''') // 定义所有需要的参数 def params = [ title: '任务完成通知', link: 'https://jenkins.example.com/job/xxx/123', buildResult: '构建成功', testResult: '测试通过率95%' ] // 先生成短模板内容,再传入长模板生成最终邮件 def shortContent = shortTemplate.make(params).toString() def finalEmail = longTemplate.make(params + [shortContent: shortContent]).toString() println(finalEmail)
方法3:闭包实现延迟解析的嵌套模板
用闭包封装模板逻辑,实现参数的延迟传递,既支持嵌套,又不会在初始化时抛出变量未定义的异常:
// 短模板:闭包接收参数,返回格式化后的字符串 def shortEmail = { title, link -> """|Title: ${title} |Link: ${link} etc. """.stripMargin() } // 长模板:调用短模板的闭包,拼接额外内容 def longEmail = { title, link, buildResult, testResult -> """|${shortEmail(title, link)} | |Build Results: ${buildResult} |Test Results: ${testResult} etc. """.stripMargin() } // 使用时直接传入所有参数 println(longEmail('任务完成通知', 'https://jenkins.example.com/job/xxx/123', '构建成功', '测试通过率95%'))
内容的提问来源于stack exchange,提问作者user12482
相关产品推荐
相关产品推荐

