如何在Filter中调用Taglib?

是否有过想在Filter中调用标签库的冲动?Luke Daley在其博文中,给出了解决之道。

文中,Luke Daley以Filter为例,演示了在其中调用createlink的方法:

import org.codehaus.groovy.grails.web.pages.GroovyPage
import org.springframework.web.context.request.RequestContextHolder

class HttpsOnlyFilter {

    def gspTagLibraryLookup 
        def filters = {
            ...
            def link = invokeTag("createLink", [
                        controller: controllerName, 
                        action: actionName, 
                        params: params, 
                        base: "https://secure.domain.com"
                    ]).toString()
            ......
    }

    def invokeTag(name, attrs = [:], body = null) {
        def namespace
        def tagName

        if (name.contains(":")) {
            def split = name.split(":", 2)
            namespace = split[0]
            tagName = split[1]
        } else {
            namespace = GroovyPage.DEFAULT_NAMESPACE
            tagName = name
        }

        GroovyPage.captureTagOutput( gspTagLibraryLookup
                                   , namespace
                                   , tagName
                                   , attrs
                                   , body
                                   , RequestContextHolder.currentRequestAttributes())
    }

}

invokeTag方法的参数为标签名、属性Map以及可选的闭包参数,如果标签名没有包含namespace,就会使用g。指定namespace的用法如下:

invokeTag("someNamespace:someTag", [param1: 1])

值得注意的是,Luke Daley也表示,如果你想在View之外调用标签库,这很可能是一个设计问题。同时,上述方法只适合在Request环境中使用,否则RequestContextHolder.currentRequestAttributes()将返回null。一种绕过这种限制的方法是用GrailsWebUtil.bindMockWebRequest()造出一个模拟环境。

除了Luke Daley介绍的方法外,还可以使用如下方式获得Createlink的内容:

def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()

//获得绝对link为:http://localhost:8080/jqac/role/index
def absoluteLink = g.createLink(controller: 'role', action: 'index',absolute:"true")

//获得相对link为:/jqac/role/index
def relativeLink = g.createLink(controller: 'role', action: 'index')

而这个方法的缺点是只能使用缺省的namespace,即g。如果要用自己定义的taglib,则可用如下方法:

def groovyq=new temp.GroovyqTagLib()
groovyq.mylink()

//GroovyqTagLib代码如下:
package temp
class GroovyqTagLib {
    static namespace = "groovyq"    
    def mylink = {        
        out << "http://localhost:8080/temp/person"        
    }
}

关于Luke Daley提供的完整代码请参见原文

By huwh - Posted on 11 五月 2011