Grails filter syntax, or, How to call a Grails Filter outside Grails

天大地大妈咪最大 提交于 2020-01-31 09:14:09

问题


Grails provides filters that run before your controllers. They're defined in classes that look like this:

class SecurityFilters {
   def filters = {
       myFilter(controller:'*', action:'*') { // What are those weird colons??
           print "I'm filtering!"
           // Code that does the filtering goes here
       }
   }
}

These work great but I would like to understand the syntax better as it doesn't look like any Groovy code I've seen before. In particular, the line above that starts with myFilter seems very odd. Is this a method definition for a method called myFilter? If so, what does :'*' mean after each parameter? I thought it might be a default parameter value but that would be ='*'. I've seen named parameters using colons in method calls before but this couldn't be a method call because I haven't defined myFilter() anywhere else.

I think I'd understand much better if someone could just tell me how to execute the filtering code from a normal Groovy class. In other words, if I have a file MyFilters.groovy that contains the lines above, how could I finish this Groovy code so it prints "I'm filtering"?

import MyFilters
def mf = new MyFilters()
mf.filters.somethingGoesHere // Help! How do I finish this line so it calls my filtering code?

回答1:


The following Groovy code would print "I'm filtering!":

class SecurityFilters {
   def filters = {
       myFilter(controller:'*', action:'*') { // What are those weird colons??
           print "I'm filtering!"
           // Code that does the filtering goes here
       }
   }   
}

class FilterDelegate {
    def methodMissing(String methodName, args) {
        // methodName == myFilter
        // args[0] == [controller:*, action:*]
        // args[1] == {print "I'm filtering!"}
        args[1].call()
    }
}

def sf = new SecurityFilters()
def filtersClosure = sf.filters
filtersClosure.delegate = new FilterDelegate()
filtersClosure.call()

In this example filters is a closure that calls a method named myFilter and passes a map and a closure. You can think of myFilter as:

myFilter([controller:'*', action:'*'], closure)

The Map can contains keys like controller, action or uri. The wildcard (*) is used when Grails attempts to match the URI from the HTTP request when it tries to determine which closure to call.

My understanding of how Grails handles filters is that a delegate loader class is used. The loader class provides a methodMissing method and creates a FilterConfig for each method call inside the filters closure. When a HTTP request is made, Grails looks through all the FilterConfig objects and tries to find a matching scope (looks in the map for a controller, action or uri and uses regexs to match on wildcards). If it finds a match it calls the closure that was passed into the method in the Filter class.




回答2:


You can't easily call filters outside of grails because they depend on a lot of plumbing that won't be set up. The line
myFilter(controller:'', action:'')
is a method definition that takes two arguments, a controller and action pattern. * means apply this filter to any object of the proceeding type. For example if we wanted to make sure users couldn't create anything unless they were authorized we would use the following filter.
controller:'*', action:'create'
This would mean that any time a create action was called the code stored in that function body would execute, but for list, show, or edit no filter would execute. If you really want detail you can always download the grails source code.
edit:
The code compiles since it's a function defined in a filter.



来源:https://stackoverflow.com/questions/1255285/grails-filter-syntax-or-how-to-call-a-grails-filter-outside-grails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!