[Grails] 在Grails中如何配置过滤器?我找不到web.xml!

zengsun 2007-12-02
突然发现找不到地方写过滤器配置,因为WEB-INF中没有web.xml文件!
使用grails war生成的war包中倒是有,看来是临时生成的!
现在我想配置自己的过滤器该往哪里写?!
agile_boy 2007-12-03
呵呵,grails的web.xml的模板不在web-app/WEB-INFO下边了,而是在GRAILS_HOME/conf/webdefault.xml,你修改相应的tag就可以了,不过最好备份。
zengsun 2007-12-03
我在RC1的文档里找到下面一段:

Participating in web.xml Generation

Grails generates the WEB-INF/web.xml file at load time, and although plugins cannot change this file directly, they can participate in the generation of the file. Essentially a plugin can provide a doWithWebDescriptor property that is assigned a block of code that gets passed the web.xml as a XmlSlurper GPathResult.

Consider the below example from the ControllersPlugin:
def doWithWebDescriptor = { webXml ->
	def mappingElement = webXml.'servlet-mapping'
	mappingElement + {
		'servlet-mapping' {
			'servlet-name'("grails")
			'url-pattern'("*.dispatch")
		}
	}
}

Here the plugin goes through gets a reference to the last <servlet-mapping> element and appends Grails' servlet to the end of it using XmlSlurper's ability to programmatically modify XML using closures and blocks.
zengsun 2007-12-03
找到方法了,原来1.0RC1提供了Filter的直接支持,不用我自己去写:
Filters
Although Grails controllers support fine grained interceptors, these are only really useful when applied to a few controllers and become difficult to manage with larger applications. Filters on the other hand can be applied across a whole group of controllers, a URI space or a to a specific action. Filters are far easier to plug-in and maintain completely separately to your main controller logic and are useful for all sorts of cross cutting concerns such as security, logging, and so on.

6.6.1 Applying Filters
To create a filter create a class that ends with the convention Filters in the grails-app/conf directory. Within this class define a code block called filters that contains the filter definitions:

class ExampleFilters {
   def filters = {
        // your filters here
   }
}

Each filter you define within the filters block has a name and a scope. The name is the method name and the scope is defined using named arguments. For example if you need to define a filter that applies to all controllers and all actions you can use wildcards:

sampleFilter(controller:'*', action:'*') {
  // interceptor definitions
}

The scope of the filter can be one of the following things:

    * A controller and/or action name pairing with optional wildcards
    * A URI

Some examples of filters include:

    * All controllers and actions

all(controller:'*', action:'*') {

}

    * Only for the BookController

justBook(controller:'book', action:'*') {

}

    * Applied to a URI space

someURIs(uri:'/book/*') {

}

    * Applied to all URIs

allURIs(uri:'/*') {

}

In addition, the order in which you define the filters dictates the order in which they are executed.
6.6.2 Filter Types
Within the body of the filter you can then define one of the following interceptor types for the filter:

    * before - Executed before the action. Can return false to indicate all future filters and the action should not execute
    * after - Executed after an action. Takes a first argument as the view model
    * afterView - Executed after view rendering

For example to fulfill the common authentication use case you could define a filter as follows:

class SecurityFilters {
   def filters = {
       loginCheck(controller:'*', action:'*') {
           before = {
              if(session.user && actionName.equals('login')) {
                  redirect(action:'login')
                  return false
               }
           }

} } }

Here the loginCheck filter uses a before interceptor to execute a block of code that checks if a user is in the session and if not redirects to the login action. Note how returning false ensure that the action itself is not executed.
6.6.3 Filter Capabilities
Filters support most of the common properties available to controllers and tag libraries including:

    * request - The HttpServletRequest object
    * response - The HttpServletResponse object
    * session - The HttpSession object
    * servletContext - The ServletContext object
    * controllers - The ApplicationContext object
    * params - The request parameters object
    * actionName - The action name that is being dispatched to
    * controllerName - The controller name that is being dispatched to

However, filters only support a subset of the methods available to controllers and tag libraries. These include:

    * redirect - For redirects to other controllers and actions
    * render - For rendering custom responses

zengsun 2007-12-03
我晕了,在我这里下面的代码居然不行!
class CompressFilters {
    def filters = {
        gzip(uri: '/js/ext/*.gz') {
            before = {
                response.addHeader('Content-Encoding', 'gzip')
            }
        }
    }
}

但是如果将uri改写为'/*',结果就可以拦截了!!!
zengsun 2007-12-04
今天上午又测试了一下,发现filter只能拦截控制器的uri。
如果是普通的资源文件(比如/js/*这样的)根本不拦截!
起不到jsp中过滤器的url-pattern匹配*.js这样的效果。
希望哪位在Grails的邮件列表提一下这件事情。
谢谢!!!
agile_boy 2007-12-04
不是很了解你的意图,不过根据你的描述和意愿,你可以开发一个plugin来解决你的问题。
在plugin中,你可以操作的元素很多的,比如web.xml,扩展spring的bean等等。
zengsun 2007-12-04
其实想做的事情很简单呀!
我在应用中使用了ext,所以我把ext-js.js用gzip压缩了一下。
这样js文件可以在浏览器中自动解压,提高网络传输的速度。
当然,我也要告诉浏览器一声。
以前的做法是用一个过滤器,
然后在匹配的url加 Content-Encoding=gzip。
本来在web.xml配置一下过滤器就可以了,但现在的问题是web.xml是动态产生的!
zengsun 2007-12-04
想了两天了,看来要做的话。还非要做个插件了。
这么简单的要求,肯定有简单的办法。
哪位帮忙想想!
zengsun 2007-12-07
问题解决了!其实很简单,
先运行
grails install-templates

然后在src目录下的templates/war/web.xml文件中写过滤器的配置就可以了!!!
Global site tag (gtag.js) - Google Analytics