2013年8月7日

Grails 2/30 使用過濾器(Filters)

Java EE 提供 Filter 機制可對 Request / Response 進行額外的程式處理,例如 Header 資訊、參數資料及產生的 HTML 內容。

有什麼情況需要用到 Filter 呢?舉例來說,如果我們要增加一個統計網站各頁面點擊次數及瀏覽器資訊的功能,可以在每個 controller 的 action 中做處理,然後將這個處理寫成函式重複呼叫使用。但是在 Filter 的幫助下,可以增加一個不會影響各 controller 現有程式碼的 Filter,然後針對特定或全部的網頁存取進行處理。

一個常見的應用範例,是過去開發 Java EE 程式經常遇到的編碼問題,諸如 Tomcat 等 container 對於瀏覽器送來的表單資料,可能需要先經過 getBytes() 的轉換才能解決中文亂碼。

String name = new String((request.getParameter("name")).getBytes("ISO-8859-1"),"utf-8");

因為 Filter 允許在 Request 主程式被執行前先做前置的處理,所以可以將編碼轉換好在交給主程式,在主程式的邏輯中,就不需要添加這種處理編碼的瑣碎細節。

Grails 之所以能正確處理 Request 表單資料的編碼,就是使用 CharacterEncodingFilter 對資料先進行過處理,所以在 Controller 中使用 params 取得的資料都已轉為正確編碼。

Grails 的 Filter 定義方式非常容易,例如:

grails create-filter Some

就會產生 grails-app/conf/test1/SomeFilters.groovy 程式碼,其內容如下。

class SomeFilters {

    def filters = {
        all(controller:'*', action:'*') {
            before = {

            }
            after = { Map model ->

            }
            afterView = { Exception e ->

            }
        }
    }
}

在 def filters 區塊內,可以用 DSL 的形式定義多組 Filter,預設定義的 all 是針對所有 controller/action 進行處理的 Filter 範例。

除了可以指定針對哪些 controller 及 action 進行 Filter 處理,也可以利用 uri 參數設定網址格式,當 Request 的網址符合就會進行處理(以 prefix 加上 ** 萬用字元設定)。

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

以下提供的範例,是利用 Grails Filter 自動將表單資料的日期,轉換成 GORM 可以自動處理的參數形式。

all(controller:'*', action:'*') {
    before = {
        log.info "Start ${controllerName}-${actionName}-Filter"

        params.each {
            key, value ->

            // Transform value from Ext JS to Grails date style
            if (value ==~ /^\d\d\d\d\-\d\d\-\d\dT\d\d:\d\d:\d\d$/) {

                // Convert into Date object
                //params[key] = Date.parse('yyyy-MM-dd HH:mm:ss', value.replaceFirst('T', ' '))

                // Convert into Grails style date string
                //params[key] = "${value}Z"
                
                // Convert into GORM properties recognization
                params[key] = 'date.struct'
                params["${key}_year"] = value.substring(0,4)
                params["${key}_month"] = value.substring(5,7)
                params["${key}_day"] = value.substring(8,10)

                params["${key}_hour"] = value.substring(11,13)
                params["${key}_minute"] = value.substring(14,16)
                params["${key}_second"] = value.substring(17,19)

                log.info "Found ${value} is a Ext JS date format, transform into Grails style"
                log.info "params[${key}] = ${params[key]}"
            }
        }
    }
    after = { Map model ->

    }
    afterView = { Exception e ->

    }
}

沒有留言:

張貼留言

lyhcode by lyhcode
歡迎轉載,請務必註明出處!