首页 文章

将表达式的值作为groovy中的表达式进行求值

提问于
浏览
0

这是我想要工作的代码

def expr = ''
    List params = []
    params << 'filter-name'
    params << 'servlet-name'
    params << 'url-pattern'

    params.each{expr = expr+ "it.'${it}'.text().trim()#"}
    expr = expr.substring(0, expr.length()-1)

    consNodes.each{
        println "data is:$"{expr}"
        println "actual : ${it.'filter-name'.text().trim()}#${it.'servlet-name'.text().trim()}#${it.'url-pattern'.text().trim()}"
}

在上面的结果来了

data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : presenceLogoutFilter##/adfAuthentication/*
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : remoteApplication##/rr/*
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : ServletADFContextFilter#GetHandler#
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : ServletADFContextFilter##/PresenceServlet/*

所以,你可以看到我构造的表达式无法进一步评估 . 有关如何使其工作的任何建议?

1 回答

  • 3

    问题是你正在创建一个 GString 这样: "it.'${it}'.text().trim()#" ,但是当你连接它时,你将它转换为 Stringexpr + "it.'${it}'.text().trim()#" . 将 GString 转换为 String 后,它不再评估表达式 . 但即使你提出它也无法解决你的问题,因为 GString 不会像你认为的那样进行评估 . 解释它的最好方法是举个例子:

    import org.codehaus.groovy.runtime.GStringImpl
    
    // What you're doing
    def a = 'John'
    def b = 'Hello, $a'
    def c = "${a}"
    
    assert b == 'Hello, $a'
    
    // What the compiler is doing (ignoring the variable name changes)
    def aa = 'John'
    def bb = 'Hello, $a'
    def cc = new GStringImpl([] as Object[], ['Hello, $a'] as String[])
    
    assert cc == 'Hello, $a'
    
    // What you want the compiler to do, but it will not.
    def aaa = 'John'
    def bbb = 'Hello, $a'
    def ccc = new GStringImpl(['John'] as Object[], ['Hello, '] as String[])
    
    assert ccc == 'Hello, John'
    

    如果你真的想,你可以手动构建 GString ,但这将非常困难 . 而且你最终取决于一个不保证在Groovy版本之间保持向后兼容的类 .

    以下是您可以做的事情:

    def params = []
    
    params << 'filter-name'
    params << 'servlet-name'
    params << 'url-pattern'
    
    def evaluators = params.collect { 
        { attr, node -> node[attr]?.text()?.trim() ?: '' }.curry(it)
    }
    
    consNodes.each { node ->
        println evaluators.collect { c -> c(node) }.join('#')    
    }
    

    输出如下所示:

    presenceLogoutFilter##/adfAuthentication/*
    remoteApplication##/rr/*
    ServletADFContextFilter#GetHandler#
    ServletADFContextFilter##/PresenceServlet/*
    

    您可以使用一个闭包列表代替单个大型表达式,每个闭包都负责评估节点属性 . 然后,您可以使用'#'加入结果 .

相关问题