有什麼情況需要用到 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 ->
}
}
沒有留言:
張貼留言