“攔截器”是框架執行一個方法之前或之后被調用的函數。它允許?[面向方面編程](http://en.wikipedia.org/wiki/Aspect-oriented_programming), 作用如下:
* 請求記錄
* 錯誤處理
* 狀態保持
在 Revel 中, 有兩種形式的攔截器:
1. 函數攔截器:請參考?[`InterceptorFunc`](http://gorevel.cn/docs/docs/godoc/intercept.html#InterceptorFunc)?接口.
* 不能掛接到某個特定的控制器方法
* 可以應用到所有的、任意的控制器上
2. 方法攔截器:一個不帶參數、并返回一個?`revel.Result`的控制器方法
* 只能攔截控制器方法
* 可以修改被調用的控制器
攔截器的執行順序與添加位置相關
## 攔截時間
在一個請求生命周期內,可以注冊四種攔截時間:
1. BEFORE: 在請求被路由到以后,并且session, flash, 參數解析之后、控制器方法被調用之前執行攔截。
2. AFTER: 在請求返回了一個結果, 但是結果被應用之前執行攔截。如果出現了panic,攔截不會被調用。
3. PANIC: 在控制器方法中或應用結果時出現panic退出后被攔截。
4. FINALLY: 在控制器方法執行完畢并且結果被應用之后被攔截。
## 結果
攔截器通常返回?`nil`, 在這種情況下,需要繼續處理請求,不能中斷。
返回一個非?`nil`?`revel.Result`的效果, 取決于攔截器被調用的時間:
1. BEFORE: 沒有進一步的攔截器被調用, 也不是一個控制器方法。
2. AFTER: 所有攔截器仍然可以運行。
3. PANIC: 所有攔截器仍然可以運行。
4. FINALLY: 所有攔截器仍然可以運行。
在任何情況下,返回的結果都將附加到任何現有的結果上:
BEFORE:返回的結果是保證是最終的。
AFTER:它可能是一個進一步的攔截器,可以返回自己的結果。
## 例如
### 函數攔截器
下面是定義和注冊函數攔截器的一個簡單例子。
~~~
func checkUser(c *revel.Controller) revel.Result {
if user := connected(c); user == nil {
c.Flash.Error("請先登錄")
return c.Redirect(App.Index)
}
return nil
}
func init() {
revel.InterceptFunc(checkUser, revel.BEFORE, &Hotels{})
}
~~~
### 方法攔截器
方法攔截器有兩種方式的簽名:
~~~
func (c AppController) example() revel.Result
func (c *AppController) example() revel.Result
~~~
下面是個同樣的例子,只能攔截一個控制器。
~~~
func (c Hotels) checkUser() revel.Result {
if user := connected(c); user == nil {
c.Flash.Error("請先登錄")
return c.Redirect(App.Index)
}
return nil
}
func init() {
revel.InterceptMethod(Hotels.checkUser, revel.BEFORE)
}
~~~