标签:
Martini核心部分Injector
type injector struct {values map[reflect.Type]reflect.Value // 保存<类型,值>对parent Injector}
type TypeMapper interface {Map(interface{}) TypeMapper // 类型映射MapTo(interface{}, interface{}) TypeMapper //将值映射为指定的类型Set(reflect.Type, reflect.Value) TypeMapper // 设置类型值Get(reflect.Type) reflect.Value}
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {t := reflect.TypeOf(f)var in = make([]reflect.Value, t.NumIn()) //如果传入的interface不是函数,则panicfor i := 0; i < t.NumIn(); i++ {argType := t.In(i)val := inj.Get(argType) // 通过函数参数类型获取函数值,injector注册器通过map保存<类型,值>对。if !val.IsValid() {return nil, fmt.Errorf("Value not found for type %v", argType)}in[i] = val}return reflect.ValueOf(f).Call(in), nil}
package mainimport ("fmt""github.com/codegangsta/inject")type myString interface{}func test1(st string, myst myString) {fmt.Println(st, myst)}var (st1 = "hello"st2 = "WORLD"- myst myString =="haha"
)func main() {inj := inject.New() \\生成injector实例inj.Map(st1) \\ st1注册为默认的类型inj.MapTo(st2, (*myString)(nil))\\ st2注册为指定的myStrig类型inj.Invoke(test1)\\ 函数test1通过参数了类型获取参数具体的值fmt.Println(inject.InterfaceOf(&myst)) // myst必须为指向interface的指针,否则panic。 }}输出:

package mainimport ("github.com/go-martini/martini""fmt""reflect")func test1(st string) string {return st}func test2(num int) int {fmt.Println(num)return num}type INT interface{}func test3(num INT, st string) string {st = st + fmt.Sprint(reflect.TypeOf(num))return st}func main() {m := martini.Classic() //生成martini实例m.Get("/hello", test2, test1)// 注册路由m.Get("/hi", test3)m.Map("a") // 注册函数参数值m.Map(1)m.MapTo("HI", (*INT)(nil))m.Run() //启动监听服务}

func Classic() *ClassicMartini {r := NewRouter()m := New() //生成martini实例m.Use(Logger()) //注册Handler,实际是往martini.handlers里append一个Handlerm.Use(Recovery())m.Use(Static("public"))m.MapTo(r, (*Routes)(nil))m.Action(r.Handle) // 注册路由处理函数,m.action=r.Handlerreturn &ClassicMartini{m, r}}

type Router interface {Routes// Group adds a group where related routes can be added.Group(string, func(Router), ...Handler)// Get adds a route for a HTTP GET request to the specified matching pattern.Get(string, ...Handler) Route// Patch adds a route for a HTTP PATCH request to the specified matching pattern.Patch(string, ...Handler) Route// Post adds a route for a HTTP POST request to the specified matching pattern.Post(string, ...Handler) Route// Put adds a route for a HTTP PUT request to the specified matching pattern.Put(string, ...Handler) Route// Delete adds a route for a HTTP DELETE request to the specified matching pattern.Delete(string, ...Handler) Route// Options adds a route for a HTTP OPTIONS request to the specified matching pattern.Options(string, ...Handler) Route// Head adds a route for a HTTP HEAD request to the specified matching pattern.Head(string, ...Handler) Route// Any adds a route for any HTTP method request to the specified matching pattern.Any(string, ...Handler) Route// AddRoute adds a route for a given HTTP method request to the specified matching pattern.AddRoute(string, string, ...Handler) Route// NotFound sets the handlers that are called when a no route matches a request. Throws a basic 404 by default.NotFound(...Handler)// Handle is the entry point for routing. This is used as a martini.HandlerHandle(http.ResponseWriter, *http.Request, Context)}
func (r *router) addRoute(method string, pattern string, handlers []Handler) *route {if len(r.groups) > 0 {groupPattern := ""h := make([]Handler, 0)for _, g := range r.groups {groupPattern += g.patternh = append(h, g.handlers...)}pattern = groupPattern + patternh = append(h, handlers...) //将注册的方法append进handlers ,请求路劲到此路由的时候会遍历调用该handlers,直到函数有返回值handlers = h}fmt.Println("handlers:", reflect.ValueOf(handlers))route := newRoute(method, pattern, handlers) // 生成指定路径方法的路由fmt.Println("route:", reflect.ValueOf(route.handlers))route.Validate()r.appendRoute(route)return route}
type route struct {method stringregex *regexp.Regexphandlers []Handlerpattern stringname string}
func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {//res.Write([]byte("hello"))m.createContext(res, req).run()}
func (m *Martini) createContext(res http.ResponseWriter, req *http.Request) *context {c := &context{inject.New(), m.handlers, m.action, NewResponseWriter(res), 0} //生成context实例c.SetParent(m)c.MapTo(c, (*Context)(nil)) //注入请求参数值c.MapTo(c.rw, (*http.ResponseWriter)(nil))c.Map(req)return c}
func (c *context) run() {for c.index <= len(c.handlers) { // 遍历handlers,handlers实际为例子中使用USE注册的logger,recovery。当左右相等时,则调用m.action,及路由处理器_, err := c.Invoke(c.handler())if err != nil {panic(err)}c.index += 1 // 计数器,用来遍历注册的路由器if c.Written() {return}}}
func Logger() Handler {return func(res http.ResponseWriter, req *http.Request, c Context, log *log.Logger) {start := time.Now()addr := req.Header.Get("X-Real-IP")if addr == "" {addr = req.Header.Get("X-Forwarded-For")if addr == "" {addr = req.RemoteAddr}}log.Printf("Started %s %s for %s", req.Method, req.URL.Path, addr)rw := res.(ResponseWriter)c.Next() //调用第二个注册的recoverylog.Printf("Completed %v %s in %v\n", rw.Status(), http.StatusText(rw.Status()), time.Since(start))}}
func Recovery() Handler {return func(c Context, log *log.Logger) {defer func() { // 捕获路由处理panicif err := recover(); err != nil {stack := stack(3)log.Printf("PANIC: %s\n%s", err, stack)// Lookup the current responsewriterval := c.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))res := val.Interface().(http.ResponseWriter)// respond with panic message while in development modevar body []byteif Env == Dev {res.Header().Set("Content-Type", "text/html")body = []byte(fmt.Sprintf(panicHtml, err, err, stack))} else {body = []byte("500 Internal Server Error")}res.WriteHeader(http.StatusInternalServerError)if nil != body {res.Write(body)}}}()c.Next() // 调用Handle进行请求路由处理}}
func (r *router) Handle(res http.ResponseWriter, req *http.Request, context Context) {fmt.Println(reflect.TypeOf(r.getRoutes()))bestMatch := NoMatchvar bestVals map[string]stringvar bestRoute *routefor _, route := range r.getRoutes() {match, vals := route.Match(req.Method, req.URL.Path)fmt.Println(match, vals)if match.BetterThan(bestMatch) {bestMatch = match // 遍历查找匹配的路径路由bestVals = valsbestRoute = routeif match == ExactMatch {break}}}if bestMatch != NoMatch {fmt.Println("bestvals", bestVals)params := Params(bestVals)context.Map(params)bestRoute.Handle(context, res) // 路由器逻辑处理return}// no routes exist, 404c := &routeContext{context, 0, r.notFounds} //没有匹配路由时,执行默认的处理函数。notfind在初始化时注册context.MapTo(c, (*Context)(nil))c.run()}
func (r *route) Handle(c Context, res http.ResponseWriter) {context := &routeContext{c, 0, r.handlers} // 初始化context,例子中对于/hello路径的请求r.handlers =[test2,test1]c.MapTo(context, (*Context)(nil))c.MapTo(r, (*Route)(nil))context.run() // 路由业务逻辑处理,遍历r.handlers获取业务逻辑方法}
func (r *routeContext) run() {for r.index < len(r.handlers) {// 遍历handlers,实际实现时可以重写这一方法,自定义要调用方法的顺序。通过设置index可以自定义调用handler := r.handlers[r.index]vals, err := r.Invoke(handler)if err != nil {panic(err)}r.index += 1// if the handler returned something, write it to the http response//如果r.handlers的函数有返回值,则把返回值写入resp并设置r.writern()的返回值为trueif len(vals) > 0 {ev := r.Get(reflect.TypeOf(ReturnHandler(nil)))handleReturn := ev.Interface().(ReturnHandler)handleReturn(r, vals)}if r.Written() {return}}}
标签:
原文地址:http://www.cnblogs.com/tanghui/p/4846156.html