
Revel是一个Go语言的web框架,其具有热编译,高性能,无状态,模块化等特性,非常适合做web开发。
这个框架源于java的 Play! Framework。
清晰的MVC结构,令其成为go语言Web框架中优秀的框架。
Revel 框架特性
热编译
编辑, 保存, 和 刷新时,Revel自动编译代码和模板,如果代码编译错误,会给出一个 错误提示,同时捕捉 运行期错误。
全栈功能
Revel 支持: 路由, 参数解析, 验证, session/flash, 模板, 缓存, 计划任务, 测试, 国际化 等功能。
高性能
Revel 基于 Go HTTP server 构建。 这是techempower发布的 最新评测结果 。在各种不同的场景下进行了多达三到十次的请求负载测试。
框架设计
同步
Go HTTP server 对于每个请求都运行在 goroutine上。Write simple callback-free code without guilt。
无状态
Revel 提供了保持Web层无状态的可预知的扩展。例如,会话数据被存储在用户的cookie中,缓存由memcached集群提供支持。
模块化
Revel框架由被称为 过滤器 的中间件组成,它实现了几乎所有的请求处理功能。 开发者可以自由地使用自定义的过滤器,比如如自定义的路由器,用以替换Revel默认的路由过滤器。
快速开始
1、安装revel之前,先安装go环境
2、安装还需要hg和git支持
3、设置GOPATH,然后把revel下载并安装到GOPATH内
mkdir ~/gocode
cd $GOPATH
go get github.com/robfig/revel
4.编译revel命令行工具,revel自己封装了go的命令行工具,创建revel项目、打包发布基本都用这个工具,执行下面的命令
go build -o bin/revel github.com/robfig/revel/cmd
5.可以将编译出来的revel命令行工具加到$PATH变量中方便调用
export PATH="$PATH:$GOPATH/bin"
6.最后验证revel是否可以工作了
$ revel help
~
~ revel! http://robfig.github.com/revel
~
usage: revel command [arguments]
The commands are:
run run a Revel application
new create a skeleton Revel application
clean clean a Revel application's temp files
package package a Revel application (e.g. for deployment)
Use "revel help [command]" for more information.
概要说明
本节简要介绍框架的几个主要组成部分:
- 路由
- 采用简单的声明性语法。反向路由类型安全。
- 控制器
- 组织端点到控制器。提供易用的数据绑定和表单验证。
- 模板
- 使用 Go 模板支持大规模应用.
- 拦截器
- 在一个函数运行之前或之后被调用. 控制器的方法都可以被注册拦截.
- 过滤器
- 通用的功能可以使用过滤器来实现.
Revel路由
路由采用声明性语法. 所有的路由都定义在一个routes文件中。 使用简单的语法匹配路由, 并从 URI 中提取参数到控制器中. 下面是带注释的示例:
# conf/routes # 这个文件定义了所有的路由 (优先级按照先后顺序) GET /login Application.Login # 匹配一个简单的路由 GET /hotels/ Hotels.Index # 匹配一个带或者不带斜线的路由 GET /hotels/:id Hotels.Show # 绑定到一个控制器参数 WS /hotels/:id/feed Hotels.Feed # WebSockets POST /hotels/:id/:action Hotels.:action # 自由绑定到一个控制器的多个方法 GET /public/*filepath Static.Serve("public") # 静态文件服务 * /:controller/:action :controller.:action # 自动捕捉所有动作,自动生成路由
反向路由以类型安全的方式生成. 例如下面的Save程序:
// 展示信息. func (c Hotels) Show(id int) revel.Result { hotel := HotelById(id) return c.Render(hotel) } // 保存信息,并重定向到Hotels.Show. func (c Hotels) Save(hotel Hotel) revel.Result { // validate and save hotel return c.Redirect(routes.Hotels.Show(hotel.Id)) }
Revel控制器
所有请求的操作都基于控制器方法实现:
- Data binding 从url或表单绑定数据并将他们传递到控制器的方法中。(也可以直接从控制器的一个参数字典中提取参数。)
- Validation 用来处理服务端验证.
- Flash flash 是一个请求中的 cookie (包括错误、消息等).
- Session 会话是加密签名的cookie, 是一个字典 map[string]string.
- Results 使用反向路由进行重定向。模板渲染,使您可以在模板中使用局部变量的名字!
下面是一个例子:
// app/controllers/app.go type Application struct { *revel.Controller } func (c Application) Register() revel.Result { title := "Register" return c.Render(title) } func (c Application) SaveUser(user models.User, verifyPassword string) revel.Result { c.Validation.Required(verifyPassword) c.Validation.Required(verifyPassword == user.Password) Message("Password does not match") user.Validate(c.Validation) if c.Validation.HasErrors() { c.Validation.Keep() c.FlashParams() return c.Redirect(routes.Application.Register()) } user.HashedPassword, _ = bcrypt.GenerateFromPassword( []byte(user.Password), bcrypt.DefaultCost) err := c.Txn.Insert(&user) if err != nil { panic(err) } c.Session["user"] = user.Username c.Flash.Success("Welcome, " + user.Name) return c.Redirect(routes.Hotels.Index()) }
Revel模板
按照惯例, Revel 轻松整合了 Go 模板 到 rest web 应用。下面是一个渲染模板的例子(参考上面展示的控制器代码)。
注意:
- Revel 自动使用控制器的方法名来查找模板。
- field 用来返回校验错误和表单数据字典的辅助函数,你可以在应用中添加任何想要的模板函数。
- title 是放到放在RenderArgs中、用于模板中的变量。(它用在示例header.html 中)
{{/* app/views/Application/Register.html */}} {{template "header.html" .}} <h1>Register:</h1> <form action="/register" method="POST"> {{with $field := field "user.Username" .}} <p class="{{$field.ErrorClass}}"> <strong>Username:</strong> <input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> * <span class="error">{{$field.Error}}</span> </p> {{end}} {{/* other fields */}} <p class="buttons"> <input type="submit" value="Register"> <a href="/">Cancel</a> </p> </form> {{template "footer.html" .}}
Revel拦截器
拦截器是请求被执行之前或之后,或响应恐慌的控制器方法。 通过嵌入一个控制器,可以共享跨越多个控制器的拦截和字段信息。
举个栗子, db 模块在初始化时打开一个数据库连接,放到一个全局变量,db.Transactional 类型添加了一个 sql.Txn 字段, 以便拦截事务的开始与提交 (或者在出错时提供回滚)。
下面是如何使用拦截的列子 (忽略了错误处理):
// github.com/revel/revel/modules/db/app/db.go var Db *sql.DB func Init() { // 读取数据库配置. Driver, _ = revel.Config.String("db.driver") Spec, _ = revel.Config.String("db.spec") // 连接到数据库. Db, _ = sql.Open(Driver, Spec) } // 为控制器添加事务管理. type Transactional struct { *revel.Controller Txn *sql.Tx } func (c *Transactional) Begin() revel.Result { c.Txn, _ = Db.Begin() return nil } func (c *Transactional) Commit() revel.Result { _ = c.Txn.Commit() c.Txn = nil return nil } func (c *Transactional) Rollback() revel.Result { _ = c.Txn.Rollback() c.Txn = nil return nil } func init() { revel.InterceptMethod((*Transactional).Begin, revel.BEFORE) revel.InterceptMethod((*Transactional).Commit, revel.AFTER) revel.InterceptMethod((*Transactional).Rollback, revel.PANIC) }
下面是如何在应用控制器中使用事务管理功能:
type Bookings struct { *revel.Controller db.Transactional // Adds .Txn user.Login // Adds .User } func (c Bookings) ShowFirstBooking() revel.Result { row := c.Txn.QueryRow(` select id, hotel_id, user_id, price, nights from Booking where UserId = ? limit 1`, c.User.Id) ... return c.Render(booking) }
Revel过滤器
过滤器是Revel程序的中间件,是具有特定签名的函数:
type Filter func(c *Controller, filterChain []Filter)
像拦截器框架等一些内建的功能就是被作为过滤器来实现:
// github.com/revel/revel/intercept.go var InterceptorFilter = func(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) }
Revel提供了开发者可以重写过滤器的默认的栈。 这很容易让开发者来选择想要使用的框架组件。
// github.com/revel/revel/filter.go // Filters 是默认的全局过滤器 // 可以在初始化应用程序时进行设置 var Filters = []Filter{ PanicFilter, // 从恐慌中恢复,并显示一个错误页面。 RouterFilter, // 使用路由表来选择合适的动作 FilterConfiguringFilter, // 用于添加或删除每个动作的过滤器的钩子. ParamsFilter, // 解析参数到 Controller.Params 中. SessionFilter, // 恢复和写入会话 cookie. FlashFilter, // 恢复和写入 flash cookie. ValidationFilter, // 还原保存验证错误并保存到新的Cookie中 I18nFilter, // 解析请求的语言 InterceptorFilter, // 执行拦截. ActionInvoker, // 执行一个动作. }
Revel 框架几乎所有的功能都是在过滤器中实现的, 而过滤器栈是作为配置的一部分直接暴露出来, 这使得Revel容易理解和模块化。
作为模块化的证明, 看看在 main server handler 中使用它是多简单啊:
// github.com/revel/revel/server.go 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) } }
更多的内容,请按教程逐步进行深入学习
转载本站内容时,请务必注明来自W3xue。
部分原创内容未经授权禁止转载,违者必究。