之前介绍了 Go Revel - main函数分析 http://www.cnblogs.com/hangxin1940/p/3263775.html

最后会调用 `revel.Run(*port)` 开启服务。

`server.go`源码 https://github.com/robfig/revel/blob/master/server.go

大致流程:

![golang_server.Run](http://images.cnblogs.com/cnblogs_com/hangxin1940/508415/o_server.Run.png "golang_server.Run")

首先获取ip地址

address := HttpAddr
if port == 0 {
port = HttpPort
}
// If the port equals zero, it means do not append port to the address.
// It can use unix socket or something else.
if port != 0 {
address = fmt.Sprintf("%s:%d", address, port)
}

如果ip地址为0,则读取配置文件中的。

生成模板加载器:

MainTemplateLoader = NewTemplateLoader(TemplatePaths)

这个模板加载器包含了当前项目模板的路径。

根据配置文件是否开启热代码加载:

// The "watch" config variable can turn on and off all watching.
// (As a convenient way to control it all together.)
if Config.BoolDefault("watch", true) {
MainWatcher = NewWatcher()
Filters = append([]Filter{WatchFilter}, Filters...)
}

这里会生成一个`Watcher`,并将它加入过滤器链,`Watcher`符合Filter接口。它会对监听目录的中文件的任何更改作出响应。

根据配置文件是否开启模板热加载:

// If desired (or by default), create a watcher for templates and routes.
// The watcher calls Refresh() on things on the first request.
if MainWatcher != nil && Config.BoolDefault("watch.templates", true) {
MainWatcher.Listen(MainTemplateLoader, MainTemplateLoader.paths...)
} else {
MainTemplateLoader.Refresh()
}

同上,它会对模板目录进行监控

开启HTTP服务:

Server = &http.Server{
Addr: address,
Handler: http.HandlerFunc(handle),
}

处理所有向`OnAppStart`注册过的方法:
runStartupHooks()

开始监听并等待连接:

if HttpSsl {
ERROR.Fatalln("Failed to listen:",
Server.ListenAndServeTLS(HttpSslCert, HttpSslKey))
} else {
ERROR.Fatalln("Failed to listen:", Server.ListenAndServe())
}

这里会视情况来开启ssl

请求处理器:

// This method handles all requests. It dispatches to handleInternal after
// handling / adapting websocket connections.
func handle(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Upgrade") == "websocket" {
websocket.Handler(func(ws *websocket.Conn) {
r.Method = "WS"
handleInternal(w, r, ws)
}).ServeHTTP(w, r)
} else {
handleInternal(w, r, nil)
}
}

func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) {
var (
req = NewRequest(r)
resp = NewResponse(w)
c = NewController(req, resp)
)
req.Websocket = ws

Filters[0](c, Filters[1:])
if c.Result != nil {
c.Result.Apply(req, resp)
}
}

所有的http请求都会在这里被处理。

首先会判断是否为`websocket`链接,如果是则打上标记,并当作websocket处理,最终都会调用`handleInternal`。

在`handleInternal`中,首先会处理过滤器链:

Filters[0](c, Filters[1:])

`Filters`是一个切片,存储`Filter`类型的方法

type Filter func(c *Controller, filterChain []Filter)

`Filter`是一个固定参数的方法,并且内部方法实现为级联递归调用。每次掉用,会传入`controller`以及当前`Filters`长度-1的一个切片,在方法最后会递归调用下去,直到传入的`Filters`切片没有元素。

自己实现的`Controller`中的方法被调用之前,所有的请求数据都会被`Filter`过滤一边,比如根据请求信息来生成路由信息,根据请求参数来转换为正确的自定义类型,运行拦截器等等。

最后,会运行:

c.Result.Apply(req, resp)

`controller`的`Result`字段会在运行过滤器链时被赋值,有可能是处理路由时的`Result`(比如404),也有可能是自定义`controller`中的`Result`(正常处理)

Go Revel - server.go 源码分析的更多相关文章

  1. kestrel Server的源码分析

    今天这一篇博客讲的是.net core 自带的kestrel server,当你开发微服务k8s部署在linux环境下,一般默认开启这个高性能服务,如果大家之前看过我的owin katana的博客,会 ...

  2. udhcp server端源码分析1--文件组织结构

    1:dhcpd.c udhcpd_main函数是整个程序的入口,依次完成的主要工作有读取配置文件信息至全局结构体.记录程序pid number.初始化lease链表.将程序作为daemon运行.死循环 ...

  3. Go Revel - Filter(过滤器)源码分析

    在 Go Revel - server.go 源码分析 http://www.cnblogs.com/hangxin1940/p/3265538.html 说到revel框架很多重要的东西都Filte ...

  4. dubbo源码分析4-基于netty的dubbo协议的server

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  5. Eureka 源码分析之 Eureka Server

    文章首发于公众号<程序员果果> 地址 : https://mp.weixin.qq.com/s/FfJrAGQuHyVrsedtbr0Ihw 简介 上一篇文章<Eureka 源码分析 ...

  6. dubbo源码分析6-telnet方式的管理实现

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  7. dubbo源码分析1-reference bean创建

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  8. dubbo源码分析2-reference bean发起服务方法调用

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  9. dubbo源码分析3-service bean的创建与发布

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

随机推荐

  1. java File类中的mkdir()和mkdirs()有什么区别

    mkdir() 只能在已经存在的目录中创建创建文件夹. mkdirs() 可以在不存在的目录中创建文件夹.诸如:a\\b,既可以创建多级目录.

  2. 【转载】抓包工具Fidder详解(主要来抓取Android中app的请求) 包括https

    文章:http://blog.csdn.net/jiangwei0910410003/article/details/19806999/ Fiddler官网:http://www.telerik.co ...

  3. 解决 p0sixspwn-v1.0.4 win版 无法定位程序输入点sqlite3_wal_checkpoint的问题

    p0sixspwn-v1.0.4 win版今天早晨发现大神( @winocm · @iH8sn0w · @SquiffyPwn) 已经发布. 下载下来运行之,发现会报错: 无法定位程序输入点sqlit ...

  4. js两个日期相减

    function dateHanle(d1,d2){ if(Date.parse(d1) - Date.parse(d2)==0) { console.log("d1等于d2"); ...

  5. JAXB--@XmlType注解标注xml生成顺序

    默认情况下,Jaxb编组出来的xml中的字段顺序是随机的,你可以使用@XmlType的propOrder属性 来指定序列化的顺序.   第一步:定义java类时,使用@XmlType(propOrde ...

  6. [转]:Android 5.0的调度作业JobScheduler

    参考:http://blog.csdn.net/cuiran/article/details/42805057 增加 JobScheduler 的同时,去掉了几个广播, CONNECTIVITY_AC ...

  7. [sql]mysql5.6cmake安装/mysql5.7二进制安装

    centos7上cmake编译安装mysql-5.6.36.tar.gz 系统环境 - 环境(安装前规划好主机名,mysql编译过程会用) [root@n1 mysql-5.6.36]# cat /e ...

  8. 实现一个简单的虚拟demo算法

    假如现在你需要写一个像下面一样的表格的应用程序,这个表格可以根据不同的字段进行升序或者降序的展示. 这个应用程序看起来很简单,你可以想出好几种不同的方式来写.最容易想到的可能是,在你的 JavaScr ...

  9. [Windows Azure] Windows Azure Identity

    Windows Azure Identity Managing identity is just as important in the public cloud is it is on premis ...

  10. Tornado中gen.coroutine详解

    1.gen.coroutine的作用 自动执行生成器 2.Future对象 在介绍异步使用之前,先了解一下Future对象的作用. Future简单可以理解为一个占位符,将来会执行的对象,类似java ...