<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Go Revel - Filter(過濾器)源碼分析

      在 Go Revel - server.go 源碼分析 http://www.rzrgm.cn/hangxin1940/p/3265538.html 說到revel框架很多重要的東西都Filters過濾器鏈中處理。 Ftilers鏈?zhǔn)钦麄€(gè)revel框架的處理核心。 ##Filters(過濾器鏈) ![golang_filters](http://images.cnblogs.com/cnblogs_com/hangxin1940/508415/o_golang-revel-filters.png "golang_filters") filter.go package revel type Filter func(c *Controller, filterChain []Filter) // Filters 為全局的過濾器鏈 // 項(xiàng)目初始化時(shí)Filters就會(huì)被設(shè)置 var Filters = []Filter{ PanicFilter, // 運(yùn)行時(shí)異常過濾器 恢復(fù)一個(gè) panics 運(yùn)行時(shí)異常并且顯示異常信息頁面 RouterFilter, // 路由過濾器 根據(jù)路由器選擇正確的Action FilterConfiguringFilter, // 自定義過濾器配置器 為每一個(gè)Action增加或刪除自定義過濾器 ParamsFilter, // 參數(shù)轉(zhuǎn)換過濾器 將請(qǐng)求的參數(shù)轉(zhuǎn)換為 Controller.Params SessionFilter, // 會(huì)話過濾器 恢復(fù)和寫入會(huì)話cookie FlashFilter, // Flash過濾器 恢復(fù)和寫入Flash信息cookie ValidationFilter, // 驗(yàn)證過濾器 恢復(fù)保存驗(yàn)證錯(cuò)誤并且從cookie中新建一個(gè) I18nFilter, // i18n過濾器 解析請(qǐng)求的語言 InterceptorFilter, // 攔截器過濾器 在Action前后運(yùn)行攔截器 ActionInvoker, // Action過濾器 調(diào)用Action方法 } // NilFilter and NilChain are helpful in writing filter tests. var ( NilFilter = func(_ *Controller, _ []Filter) {} NilChain = []Filter{NilFilter} ) 符合`func(c *Controller, filterChain []Filter)`這兩種參數(shù)形式的函數(shù),均可以當(dāng)作過濾器。 Filter是一個(gè)固定參數(shù)的方法,并且內(nèi)部方法實(shí)現(xiàn)為級(jí)聯(lián)遞歸調(diào)用。每次掉用,會(huì)傳入controller以及當(dāng)前Filters長(zhǎng)度-1的一個(gè)切片,在方法最后會(huì)遞歸調(diào)用下去,直到傳入的Filters切片沒有元素。 通過filterconfig可以很方便的添加自定義過濾器,如源碼中注釋的示例: // FilterConfigurator allows the developer configure the filter chain on a // per-controller or per-action basis. The filter configuration is applied by // the FilterConfiguringFilter, which is itself a filter stage. For example, // // Assuming: // Filters = []Filter{ // RouterFilter, // FilterConfiguringFilter, // SessionFilter, // ActionInvoker, // } // // Add: // FilterAction(App.Action). // Add(OtherFilter) // // => RouterFilter, FilterConfiguringFilter, SessionFilter, OtherFilter, ActionInvoker // // Remove: // FilterAction(App.Action). // Remove(SessionFilter) // // => RouterFilter, FilterConfiguringFilter, OtherFilter, ActionInvoker // // Insert: // FilterAction(App.Action). // Insert(OtherFilter, revel.BEFORE, SessionFilter) // // => RouterFilter, FilterConfiguringFilter, OtherFilter, SessionFilter, ActionInvoker // // Filter modifications may be combined between Controller and Action. For example: // FilterController(App{}). // Add(Filter1) // FilterAction(App.Action). // Add(Filter2) // // .. would result in App.Action being filtered by both Filter1 and Filter2. // // Note: the last filter stage is not subject to the configurator. In // particular, Add() adds a filter to the second-to-last place. 只需要對(duì)要過濾的`Controller`或`Action`應(yīng)用到`FilterController`或`FilterAction`函數(shù),并`Add`添加自定義過濾器就行了。 Filters的調(diào)用方式?jīng)Q定了過濾器鏈的調(diào)用是有序的,在默認(rèn)的`Filters`切片中,調(diào)用的順序既是其元素定義的順序。 ##1. PanicFilter(處理運(yùn)行時(shí)異常) PanicFilter用來處理所有運(yùn)行時(shí)異常信息,它使用`recover()`來捕獲所有運(yùn)行時(shí)異常。它被安排為第一個(gè)過濾器是有原因的。 定義如下: // PanicFilter wraps the action invocation in a protective defer blanket that // converts panics into 500 error pages. func PanicFilter(c *Controller, fc []Filter) { defer func() { if err := recover(); err != nil { handleInvocationPanic(c, err) } }() fc[0](c, fc[1:]) } // This function handles a panic in an action invocation. // It cleans up the stack trace, logs it, and displays an error page. func handleInvocationPanic(c *Controller, err interface{}) { error := NewErrorFromPanic(err) if error == nil { ERROR.Print(err, "\n", string(debug.Stack())) c.Response.Out.WriteHeader(500) c.Response.Out.Write(debug.Stack()) return } ERROR.Print(err, "\n", error.Stack) c.Result = c.RenderError(error) } 首先會(huì)定一個(gè)defer閉包,之后繼續(xù)調(diào)用過濾器鏈。 這很像一個(gè)遞歸,確保了它以后的所有過濾器鏈執(zhí)行完后這個(gè)defer閉包才會(huì)執(zhí)行。而`PanicFilter`又是第一個(gè)被執(zhí)行的過濾器,這樣在運(yùn)行`recover()`時(shí),能確保它會(huì)捕獲所有異常。 ##2. RouterFilter(處理路由) 項(xiàng)目中`conf/routes`配置的路由信息,將在這里被正確的轉(zhuǎn)到各個(gè)`Controller`/`Action`。 func RouterFilter(c *Controller, fc []Filter) { // Figure out the Controller/Action var route *RouteMatch = MainRouter.Route(c.Request.Request) if route == nil { c.Result = c.NotFound("No matching route found") return } // The route may want to explicitly return a 404. if route.Action == "404" { c.Result = c.NotFound("(intentionally)") return } // Set the action. if err := c.SetAction(route.ControllerName, route.MethodName); err != nil { c.Result = c.NotFound(err.Error()) return } // Add the route and fixed params to the Request Params. c.Params.Route = route.Params // Add the fixed parameters mapped by name. // TODO: Pre-calculate this mapping. for i, value := range route.FixedParams { if c.Params.Fixed == nil { c.Params.Fixed = make(url.Values) } if i < len(c.MethodType.Args) { arg := c.MethodType.Args[i] c.Params.Fixed.Set(arg.Name, value) } else { WARN.Println("Too many parameters to", route.Action, "trying to add", value) break } } fc[0](c, fc[1:]) } 首先,通過檢查請(qǐng)求信息,生成`RouteMatch`對(duì)象,它包含了一個(gè)路由所對(duì)應(yīng)的信息。 然后為`Controller`參數(shù)設(shè)置正確的請(qǐng)求信息,如實(shí)例化一個(gè)目標(biāo)`Controller`、`Params`請(qǐng)求參數(shù)等,如果未找到正確路由則設(shè)置`Result`,并直接返回,終止過濾器鏈的調(diào)用。 ##3. FilterConfiguringFilter(處理自定義過濾器) 前面講過自定義過濾器的實(shí)現(xiàn),這里則是如何調(diào)用它們 // FilterConfiguringFilter is a filter stage that customizes the remaining // filter chain for the action being invoked. func FilterConfiguringFilter(c *Controller, fc []Filter) { if newChain := getOverrideChain(c.Name, c.Action); newChain != nil { newChain[0](c, newChain[1:]) return } fc[0](c, fc[1:]) } // getOverrideChain retrieves the overrides for the action that is set func getOverrideChain(controllerName, action string) []Filter { if newChain, ok := filterOverrides[action]; ok { return newChain } if newChain, ok := filterOverrides[controllerName]; ok { return newChain } return nil } 首先從`filterOverrides`這個(gè)map中匹配是否存在相應(yīng)`Controller`/`Action`的過濾器,如果存在則鏈?zhǔn)秸{(diào)用。 自定義過濾器全部調(diào)用完后,則進(jìn)入下一環(huán)節(jié)過濾器的調(diào)用。 ##4. ParamsFilter(處理請(qǐng)求表單參數(shù)) func ParamsFilter(c *Controller, fc []Filter) { ParseParams(c.Params, c.Request) // Clean up from the request. defer func() { // Delete temp files. if c.Request.MultipartForm != nil { err := c.Request.MultipartForm.RemoveAll() if err != nil { WARN.Println("Error removing temporary files:", err) } } for _, tmpFile := range c.Params.tmpFiles { err := os.Remove(tmpFile.Name()) if err != nil { WARN.Println("Could not remove upload temp file:", err) } } }() fc[0](c, fc[1:]) } `ParamsFilter`把請(qǐng)求中的表單參數(shù)或者上傳的文件正確轉(zhuǎn)換為相應(yīng)的類型或者臨時(shí)文件保存為`Controller.Params`。 它也使用了`defer`閉包,確保在過濾器鏈退出時(shí)把生成的臨時(shí)文件全部刪除。 ##5. SessionFilter(處理會(huì)話cookies) func SessionFilter(c *Controller, fc []Filter) { c.Session = restoreSession(c.Request.Request) fc[0](c, fc[1:]) // Store the session (and sign it). c.SetCookie(c.Session.cookie()) } 這里只是簡(jiǎn)單的從請(qǐng)求獲取cookie,并在所有過濾器鏈調(diào)用完后再調(diào)用`Controller`的`SetCookie`方法將cookie發(fā)送給客戶端。 在最后調(diào)用`SetCookie`方法,是因?yàn)閌SessionFilter`之后的過濾器可能會(huì)對(duì)cookies進(jìn)行操作。 ##6. FlashFilter(處理Flash cookies) flash的生命周期很短,僅限于一次請(qǐng)求。 func FlashFilter(c *Controller, fc []Filter) { c.Flash = restoreFlash(c.Request.Request) c.RenderArgs["flash"] = c.Flash.Data fc[0](c, fc[1:]) // Store the flash. var flashValue string for key, value := range c.Flash.Out { flashValue += "\x00" + key + ":" + value + "\x00" } c.SetCookie(&http.Cookie{9 Name: CookiePrefix + "_FLASH", Value: url.QueryEscape(flashValue), Path: "/", }) } 這里會(huì)設(shè)置`Controller`對(duì)象Flash相關(guān)的字段,然后調(diào)用后面的過濾器鏈,并在最后將這個(gè)Flash 寫入cookie ##7. ValidationFilter(處理驗(yàn)證器) 這里會(huì)在每次調(diào)用controller之前為每個(gè)controller實(shí)例創(chuàng)建一個(gè)`Validation`驗(yàn)證器: func ValidationFilter(c *Controller, fc []Filter) { errors, err := restoreValidationErrors(c.Request.Request) c.Validation = &Validation{ Errors: errors, keep: false, } hasCookie := (err != http.ErrNoCookie) fc[0](c, fc[1:]) // Add Validation errors to RenderArgs. c.RenderArgs["errors"] = c.Validation.ErrorMap() // Store the Validation errors var errorsValue string if c.Validation.keep { for _, error := range c.Validation.Errors { if error.Message != "" { errorsValue += "\x00" + error.Key + ":" + error.Message + "\x00" } } } // When there are errors from Validation and Keep() has been called, store the // values in a cookie. If there previously was a cookie but no errors, remove // the cookie. if errorsValue != "" { c.SetCookie(&http.Cookie{ Name: CookiePrefix + "_ERRORS", Value: url.QueryEscape(errorsValue), Path: "/", }) } else if hasCookie { c.SetCookie(&http.Cookie{ Name: CookiePrefix + "_ERRORS", MaxAge: -1, Path: "/", }) } } // Restore Validation.Errors from a request. func restoreValidationErrors(req *http.Request) ([]*ValidationError, error) { var ( err error cookie *http.Cookie errors = make([]*ValidationError, 0, 5) ) if cookie, err = req.Cookie(CookiePrefix + "_ERRORS"); err == nil { ParseKeyValueCookie(cookie.Value, func(key, val string) { errors = append(errors, &ValidationError{ Key: key, Message: val, }) }) } return errors, err } // Register default validation keys for all calls to Controller.Validation.Func(). // Map from (package).func => (line => name of first arg to Validation func) // E.g. "myapp/controllers.helper" or "myapp/controllers.(*Application).Action" // This is set on initialization in the generated main.go file. var DefaultValidationKeys map[string]map[int]string 首先,`restoreValidationErrors`方法嘗試從客戶端請(qǐng)求的cookie中恢復(fù)出錯(cuò)的驗(yàn)證信息。 然后為`Controller`實(shí)例創(chuàng)建一個(gè)`Validation`對(duì)象。 接著繼續(xù)過濾器鏈的調(diào)用。 所有過濾器鏈調(diào)用完后,根據(jù)`Validation.keep`得值判斷是否將錯(cuò)誤的驗(yàn)證信息寫入cookies中從而在整個(gè)繪畫中保存驗(yàn)證信息。 通常,驗(yàn)證器在自定義`Controller`的`Action`中使用,根據(jù)情況可以調(diào)用`Validation.keep`來將錯(cuò)誤信息保持在會(huì)話中。 `DefaultValidationKeys`中存儲(chǔ)的是整個(gè)項(xiàng)目源碼中所有調(diào)用驗(yàn)證的行號(hào)與名稱,在`main.go`中為它賦值。在調(diào)用驗(yàn)證之后,默認(rèn)會(huì)調(diào)用她的`apply`方法, 它會(huì)將`DefaultValidationKeys`存儲(chǔ)的行號(hào)等詳細(xì)信息組裝為`ValidationResult`。 關(guān)于`DefaultValidationKeys`的生成 具體請(qǐng)移步 Go Revel - main函數(shù)分析 http://www.rzrgm.cn/hangxin1940/p/3263775.html ##8. I18nFilter(處理國際化i18n) 判斷header或cookie中是否存在語言聲明字段,然后定義`controller`的`Request.Locale`對(duì)象,方便后續(xù)工作中處理國際化i18n ##9. InterceptorFilter(處理攔截器) 執(zhí)行4種攔截器: `BEFORE`、`AFTER`、`PANIC`、`FINALLY` func InterceptorFilter(c *Controller, fc []Filter) { defer invokeInterceptors(FINALLY, c) defer func() { if err := recover(); err != nil { invokeInterceptors(PANIC, c) panic(err) } }() // Invoke the BEFORE interceptors and return early, if we get a result. invokeInterceptors(BEFORE, c) if c.Result != nil { return } fc[0](c, fc[1:]) invokeInterceptors(AFTER, c) } func invokeInterceptors(when When, c *Controller) { var ( app = reflect.ValueOf(c.AppController) result Result ) for _, intc := range getInterceptors(when, app) { resultValue := intc.Invoke(app) if !resultValue.IsNil() { result = resultValue.Interface().(Result) } if when == BEFORE && result != nil { c.Result = result return } } if result != nil { c.Result = result } } 第一行的`defer`執(zhí)行`FINALLY`階段的攔截器,它在方法退出前執(zhí)行,第二個(gè)`defer`閉包則捕捉運(yùn)行時(shí)異常,用以攔截處理`PANIC`階段的攔截器,它會(huì)在`FINALLY`之前調(diào)用,此時(shí)能捕獲絕大部分的運(yùn)行時(shí)異常。 `BEFORE`、`AFTER`攔截器分別在運(yùn)行過濾器鏈代碼的前后執(zhí)行,而此時(shí)整個(gè)過濾器鏈已剩下最后一個(gè)過濾器沒調(diào)用了。 ##10. ActionInvoker(由開發(fā)者處理Action請(qǐng)求) 到了這里,代碼就交給了開發(fā)者,它會(huì)根據(jù)請(qǐng)求找到并執(zhí)行自定義的`controller`中的`action`,這里完全有開發(fā)者做主。 func ActionInvoker(c *Controller, _ []Filter) { // Instantiate the method. methodValue := reflect.ValueOf(c.AppController).MethodByName(c.MethodType.Name) // Collect the values for the method's arguments. var methodArgs []reflect.Value for _, arg := range c.MethodType.Args { // If they accept a websocket connection, treat that arg specially. var boundArg reflect.Value if arg.Type == websocketType { boundArg = reflect.ValueOf(c.Request.Websocket) } else { TRACE.Println("Binding:", arg.Name, "as", arg.Type) boundArg = Bind(c.Params, arg.Name, arg.Type) } methodArgs = append(methodArgs, boundArg) } var resultValue reflect.Value if methodValue.Type().IsVariadic() { resultValue = methodValue.CallSlice(methodArgs)[0] } else { resultValue = methodValue.Call(methodArgs)[0] } if resultValue.Kind() == reflect.Interface && !resultValue.IsNil() { c.Result = resultValue.Interface().(Result) } } 這里通過反射來調(diào)用之前在`RouterFilter`中生成的`contrller`實(shí)例的`Action`方法,并將轉(zhuǎn)換過的請(qǐng)求參數(shù)傳入,這里就真正進(jìn)入自己構(gòu)造的controller中了。 所有過濾器鏈處理完后,會(huì)返回至`server.go`中。 移步至 Go Revel - server.go 源碼分析 http://www.rzrgm.cn/hangxin1940/p/3265538.html

      posted on 2013-08-18 19:25  黑暗伯爵  閱讀(3540)  評(píng)論(0)    收藏  舉報(bào)

      導(dǎo)航

      主站蜘蛛池模板: 人妻无码中文专区久久app| 欧美18videosex性欧美黑吊 | 四虎永久在线高清免费看| 人妻色综合网站| 一出一进一爽一粗一大视频| 国产短视频一区二区三区| 国产高在线精品亚洲三区| 成人免费无遮挡在线播放| 亚洲电影天堂av2017| 在线观看潮喷失禁大喷水无码| 欧美人与动牲猛交A欧美精品| 131mm少妇做爰视频| 九九热99精品视频在线| 国产一区二区不卡自拍| 另类 专区 欧美 制服| 极品蜜桃臀一区二区av| 国内自拍小视频在线看| 亚洲男人天堂2018| 国产成a人片在线观看视频下载| 激情在线一区二区三区视频 | 亚洲精品综合网二三区| 少妇久久久被弄到高潮| 内射干少妇亚洲69XXX| 中文字幕久久久久人妻中出| 亚洲日本欧洲二区精品| 成人影片一区免费观看| 亚洲中文字幕精品一区二区三区 | 大连市| 熟女国产精品一区二区三| 亚洲情A成黄在线观看动漫尤物 | 3d无码纯肉动漫在线观看| 久久精产国品一二三产品| 国产成人亚洲欧美二区综合| 人妻中文字幕不卡精品| 日韩人妻无码一区二区三区| 国产成人精品亚洲日本语言| 福利一区二区在线观看| 色视频不卡一区二区三区| 日本边添边摸边做边爱| 老鸭窝在线视频| 国产精品第一区亚洲精品|