课程表

Revel课程

工具箱
速查手册

Revel教程

当前位置:免费教程 » 程序设计 » Revel
Revel

Revel是一个Go语言的web框架,其具有热编译,高性能,无状态,模块化等特性,非常适合做web开发。

这个框架源于java的 Play! Framework。

清晰的MVC结构,令其成为go语言Web框架中优秀的框架。

开始学习Revel!


Revel 中文社区

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内

  1. mkdir ~/gocode
  2. cd $GOPATH
  3. go get github.com/robfig/revel

4.编译revel命令行工具,revel自己封装了go的命令行工具,创建revel项目、打包发布基本都用这个工具,执行下面的命令

  1. go build -o bin/revel github.com/robfig/revel/cmd

5.可以将编译出来的revel命令行工具加到$PATH变量中方便调用

  1. export PATH="$PATH:$GOPATH/bin"

6.最后验证revel是否可以工作了

  1. $ revel help
  2. ~
  3. ~ revel! http://robfig.github.com/revel
  4. ~
  5. usage: revel command [arguments]
  6. The commands are:
  7. run run a Revel application
  8. new create a skeleton Revel application
  9. clean clean a Revel application's temp files
  10. package package a Revel application (e.g. for deployment)
  11. Use "revel help [command]" for more information.

概要说明

本节简要介绍框架的几个主要组成部分:

路由
采用简单的声明性语法。反向路由类型安全。
控制器
组织端点到控制器。提供易用的数据绑定和表单验证。
模板
使用 Go 模板支持大规模应用.
拦截器
在一个函数运行之前或之后被调用. 控制器的方法都可以被注册拦截.
过滤器
通用的功能可以使用过滤器来实现.

Revel路由

路由采用声明性语法. 所有的路由都定义在一个routes文件中。 使用简单的语法匹配路由, 并从 URI 中提取参数到控制器中. 下面是带注释的示例:

  1. # conf/routes
  2. # 这个文件定义了所有的路由 (优先级按照先后顺序)
  3. GET /login Application.Login # 匹配一个简单的路由
  4. GET /hotels/ Hotels.Index # 匹配一个带或者不带斜线的路由
  5. GET /hotels/:id Hotels.Show # 绑定到一个控制器参数
  6. WS /hotels/:id/feed Hotels.Feed # WebSockets
  7. POST /hotels/:id/:action Hotels.:action # 自由绑定到一个控制器的多个方法
  8. GET /public/*filepath Static.Serve("public") # 静态文件服务
  9. * /:controller/:action :controller.:action # 自动捕捉所有动作,自动生成路由

反向路由以类型安全的方式生成. 例如下面的Save程序:

  1. // 展示信息.
  2. func (c Hotels) Show(id int) revel.Result {
  3. hotel := HotelById(id)
  4. return c.Render(hotel)
  5. }
  6.  
  7. // 保存信息,并重定向到Hotels.Show.
  8. func (c Hotels) Save(hotel Hotel) revel.Result {
  9. // validate and save hotel
  10. return c.Redirect(routes.Hotels.Show(hotel.Id))
  11. }

Revel控制器

所有请求的操作都基于控制器方法实现:

  • Data binding 从url或表单绑定数据并将他们传递到控制器的方法中。(也可以直接从控制器的一个参数字典中提取参数。)
  • Validation 用来处理服务端验证.
  • Flash flash 是一个请求中的 cookie (包括错误、消息等).
  • Session 会话是加密签名的cookie, 是一个字典 map[string]string.
  • Results 使用反向路由进行重定向。模板渲染,使您可以在模板中使用局部变量的名字!

下面是一个例子:

  1. // app/controllers/app.go
  2.  
  3. type Application struct {
  4. *revel.Controller
  5. }
  6.  
  7. func (c Application) Register() revel.Result {
  8. title := "Register"
  9. return c.Render(title)
  10. }
  11.  
  12. func (c Application) SaveUser(user models.User, verifyPassword string) revel.Result {
  13. c.Validation.Required(verifyPassword)
  14. c.Validation.Required(verifyPassword == user.Password)
  15. Message("Password does not match")
  16. user.Validate(c.Validation)
  17.  
  18. if c.Validation.HasErrors() {
  19. c.Validation.Keep()
  20. c.FlashParams()
  21. return c.Redirect(routes.Application.Register())
  22. }
  23.  
  24. user.HashedPassword, _ = bcrypt.GenerateFromPassword(
  25. []byte(user.Password), bcrypt.DefaultCost)
  26. err := c.Txn.Insert(&user)
  27. if err != nil {
  28. panic(err)
  29. }
  30.  
  31. c.Session["user"] = user.Username
  32. c.Flash.Success("Welcome, " + user.Name)
  33. return c.Redirect(routes.Hotels.Index())
  34. }

Revel模板

按照惯例, Revel 轻松整合了 Go 模板 到 rest web 应用。下面是一个渲染模板的例子(参考上面展示的控制器代码)。

注意:

  • Revel 自动使用控制器的方法名来查找模板。
  • field 用来返回校验错误和表单数据字典的辅助函数,你可以在应用中添加任何想要的模板函数。
  • title 是放到放在RenderArgs中、用于模板中的变量。(它用在示例header.html 中)
  1. {{/* app/views/Application/Register.html */}}
  2.  
  3. {{template "header.html" .}}
  4.  
  5. <h1>Register:</h1>
  6. <form action="/register" method="POST">
  7. {{with $field := field "user.Username" .}}
  8. <p class="{{$field.ErrorClass}}">
  9. <strong>Username:</strong>
  10. <input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> *
  11. <span class="error">{{$field.Error}}</span>
  12. </p>
  13. {{end}}
  14.  
  15. {{/* other fields */}}
  16.  
  17. <p class="buttons">
  18. <input type="submit" value="Register"> <a href="/">Cancel</a>
  19. </p>
  20. </form>
  21.  
  22. {{template "footer.html" .}}

Revel拦截器

拦截器是请求被执行之前或之后,或响应恐慌的控制器方法。 通过嵌入一个控制器,可以共享跨越多个控制器的拦截和字段信息。

举个栗子, db 模块在初始化时打开一个数据库连接,放到一个全局变量,db.Transactional 类型添加了一个 sql.Txn 字段, 以便拦截事务的开始与提交 (或者在出错时提供回滚)。

下面是如何使用拦截的列子 (忽略了错误处理):

  1. // github.com/revel/revel/modules/db/app/db.go
  2.  
  3. var Db *sql.DB
  4.  
  5. func Init() {
  6. // 读取数据库配置.
  7. Driver, _ = revel.Config.String("db.driver")
  8. Spec, _ = revel.Config.String("db.spec")
  9.  
  10. // 连接到数据库.
  11. Db, _ = sql.Open(Driver, Spec)
  12. }
  13.  
  14. // 为控制器添加事务管理.
  15. type Transactional struct {
  16. *revel.Controller
  17. Txn *sql.Tx
  18. }
  19.  
  20. func (c *Transactional) Begin() revel.Result {
  21. c.Txn, _ = Db.Begin()
  22. return nil
  23. }
  24.  
  25. func (c *Transactional) Commit() revel.Result {
  26. _ = c.Txn.Commit()
  27. c.Txn = nil
  28. return nil
  29. }
  30.  
  31. func (c *Transactional) Rollback() revel.Result {
  32. _ = c.Txn.Rollback()
  33. c.Txn = nil
  34. return nil
  35. }
  36.  
  37. func init() {
  38. revel.InterceptMethod((*Transactional).Begin, revel.BEFORE)
  39. revel.InterceptMethod((*Transactional).Commit, revel.AFTER)
  40. revel.InterceptMethod((*Transactional).Rollback, revel.PANIC)
  41. }

下面是如何在应用控制器中使用事务管理功能:

  1. type Bookings struct {
  2. *revel.Controller
  3. db.Transactional // Adds .Txn
  4. user.Login // Adds .User
  5. }
  6.  
  7. func (c Bookings) ShowFirstBooking() revel.Result {
  8. row := c.Txn.QueryRow(`
  9. select id, hotel_id, user_id, price, nights
  10. from Booking
  11. where UserId = ?
  12. limit 1`, c.User.Id)
  13. ...
  14. return c.Render(booking)
  15. }

Revel过滤器

过滤器是Revel程序的中间件,是具有特定签名的函数:

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

像拦截器框架等一些内建的功能就是被作为过滤器来实现:

  1. // github.com/revel/revel/intercept.go
  2.  
  3. var InterceptorFilter = func(c *Controller, fc []Filter) {
  4. defer invokeInterceptors(FINALLY, c)
  5. defer func() {
  6. if err := recover(); err != nil {
  7. invokeInterceptors(PANIC, c)
  8. panic(err)
  9. }
  10. }()
  11.  
  12. // Invoke the BEFORE interceptors and return early, if we get a result.
  13. invokeInterceptors(BEFORE, c)
  14. if c.Result != nil {
  15. return
  16. }
  17.  
  18. fc[0](c, fc[1:])
  19. invokeInterceptors(AFTER, c)
  20. }

Revel提供了开发者可以重写过滤器的默认的栈。 这很容易让开发者来选择想要使用的框架组件。

  1. // github.com/revel/revel/filter.go
  2.  
  3. // Filters 是默认的全局过滤器
  4. // 可以在初始化应用程序时进行设置
  5. var Filters = []Filter{
  6. PanicFilter, // 从恐慌中恢复,并显示一个错误页面。
  7. RouterFilter, // 使用路由表来选择合适的动作
  8. FilterConfiguringFilter, // 用于添加或删除每个动作的过滤器的钩子.
  9. ParamsFilter, // 解析参数到 Controller.Params 中.
  10. SessionFilter, // 恢复和写入会话 cookie.
  11. FlashFilter, // 恢复和写入 flash cookie.
  12. ValidationFilter, // 还原保存验证错误并保存到新的Cookie中
  13. I18nFilter, // 解析请求的语言
  14. InterceptorFilter, // 执行拦截.
  15. ActionInvoker, // 执行一个动作.
  16. }

Revel 框架几乎所有的功能都是在过滤器中实现的, 而过滤器栈是作为配置的一部分直接暴露出来, 这使得Revel容易理解和模块化。

作为模块化的证明, 看看在 main server handler 中使用它是多简单啊:

  1. // github.com/revel/revel/server.go
  2.  
  3. func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) {
  4. var (
  5. req = NewRequest(r)
  6. resp = NewResponse(w)
  7. c = NewController(req, resp)
  8. )
  9. req.Websocket = ws
  10.  
  11. Filters[0](c, Filters[1:])
  12. if c.Result != nil {
  13. c.Result.Apply(req, resp)
  14. }
  15. }

更多的内容,请按教程逐步进行深入学习


转载本站内容时,请务必注明来自W3xue。
部分原创内容未经授权禁止转载,违者必究。
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号