• 路由
    • 一个简单的路由
    • 斜线后缀
    • URL 参数
    • * 通配符
    • Websockets
    • 静态文件服务
    • 固定参数
    • 自动路由
    • 反转路由

    路由

    路由定义在一个单独的 routes 文件中.

    路由定义规则是:

    1. (METHOD) (URL Pattern) (Controller.Action)

    下面演示路由的定义:

    1. # conf/routes
    2. # 这个文件定义了应用程序的所有路由 (优先级按照先后顺序)
    3. GET /login App.Login # 一个简单的路由
    4. GET /hotels/ Hotels.Index # 一个简单的路由,带不带斜线后缀都一样
    5. GET /hotels/:id Hotels.Show # 绑定到一个URI参数id
    6. WS /hotels/:id/feed Hotels.Feed # WebSockets
    7. POST /hotels/:id/:action Hotels.:action # 自动匹配路由到一个控制器的多个方法
    8. GET /public/*filepath Static.Serve("public") # 映射到 /public/下的静态文件
    • /:controller/:action :controller.:action # 捕获所有控制器方法; 自动生成 URL
      接下来我们一个个看。最后在看看如何实现 反转路由 – 生成URL调用一个特定的方法

    一个简单的路由

    1. GET /login App.Login

    直接将一个URL精确匹配到一个控制器方法。

    斜线后缀

    1. GET /hotels/ Hotels.Index

    /hotels/hotels/ 路由都会调用 Hotels.Index 方法。反转 Hotels.Index产生的URL则会包含斜线后缀。

    斜线后缀无法用于区分两个同名路由,/login/login/是一样的

    URL 参数

    1. GET /hotels/:id Hotels.Show

    Revel可以从URL重提取参数并绑定到控制器方法。:id 变量会尝试匹配除了斜线后缀外的任意值。举个栗子,/hotels/123/hotels/abc 都与这个路由匹配。

    提取的参数保存到 Controller.Params map中, 绑定到控制器方法Show中. 举个栗子:

    1. func (c Hotels) Show(id int) revel.Result {
    2. ...
    3. }

    1. func (c Hotels) Show() revel.Result {
    2. var id string = c.Params.Get("id")
    3. ...
    4. }

    1. func (c Hotels) Show() revel.Result {
    2. var id int
    3. c.Params.Bind(&id, "id")
    4. ...
    5. }

    * 通配符

    1. GET /public/*filepath Static.Serve("public")

    路由器识别第二种通配符。通配符必须放到路由的最后一个元素前, 匹配所有以*之前路径开头的URL

    这里的路由将匹配 “/public/”和以他开头的所有路径

    Websockets

    1. WS /hotels/:id/feed Hotels.Feed

    Websockets 以同样的方式接受请求, 它使用 WS标识符

    相应的方法签名如下:

    1. func (c Hotels) Feed(ws *websocket.Conn, id int) revel.Result {
    2. ...
    3. }

    静态文件服务

    1. GET /public/*filepath Static.Serve("public")
    2. GET /favicon.ico Static.Serve("public","img/favicon.png")

    对于使用2个参数的Static.Serve, 在 , 之间不允许有空格,due to how encoding/csv works.

    对于静态资源服务, Revel 有static 模块支持, 包含一个单一的带两个参数的静态 控制器

    • 前缀 (字符串) - 指定到静态文件根目录的相对或绝对路径
    • 文件路径 (字符串) - 指定文件的相对路径。
      (可以参考 代码结构布局图 了解更多信息)

    固定参数

    路由可以绑定一个或多个参数到控制器方法中,举个栗子:

    1. GET /products/:id ShowList("PRODUCT")
    2. GET /menus/:id ShowList("MENU")

    参数通过在路由中的位置绑定到参数名,这里,列表中的字符串将被绑定到方法的第一个参数中。

    下面是几种有用的情况:

    • 一组相似功能的方法
    • 相同功能的方法,但工作在不同的模式
    • 相同功能的方法,但操作不同的数据类型

    自动路由

    1. POST /hotels/:id/:action Hotels.:action
    • /:controller/:action :controller.:action
      URL 的提取也可以用于确定调用哪个控制器方法。匹配规则不区分大小写

    第一个例子匹配下面的路由

    1. /hotels/1/show => Hotels.Show
    2. /hotels/2/details => Hotels.Details

    第二个例子匹配应用程序中的任意的方法

    1. /app/login => App.Login
    2. /users/list => Users.List

    由于匹配控制器和方法不区分大小写,下面的路由也匹配

    1. /APP/LOGIN => App.Login
    2. /Users/List => Users.List

    使用自动路由作为一个捕获所有的方法(例如文件中的最后一个路由),用于快速挂接方法,to non-vanity URLs,尤其是在与反向路由器一起使用是很有用的。

    反转路由

    对于以下几种情况,使用反转路由生成URLs是一个很好的方法,

    • 避免拼写错误
    • 编译器确保反向路由有正确的数量和参数类型。
    • 修改路由,仅需要在routes文件中修改一次
      构建程序时,Revel自动生成一个路由包app/routes,一条语句就可以使用:
    1. routes.Controller.Action(param1, param2)

    上面的语句使用Controller.Action和参数返回一个字符串类型的 URL,下面给出一个完整的例子:

    1. import (
    2. "github.com/revel/revel"
    3. "project/app/routes"
    4. )
    5.  
    6. type App struct { *revel.Controller }
    7.  
    8. // 生成一个表单页面
    9. func (c App) ViewForm(username string) revel.Result {
    10. return c.Render(username)
    11. }
    12.  
    13. // 处理提交的表单
    14. func (c App) ProcessForm(username, input string) revel.Result {
    15. ...
    16. if c.Validation.HasErrors() {
    17. c.Validation.Keep()
    18. c.Flash.Error("Form invalid. Try again.")
    19. return c.Redirect(routes.App.ViewForm(username)) // <--- 反转路由
    20. }
    21. c.Flash.Success("Form processed!")
    22. return c.Redirect(routes.App.ViewConfirmation(username, input)) // <--- 反转路由
    23. }

    局限性: Only primitiveparameters to a route are typed due to the possibility of circular imports.Non-primitive parameters are typed as interface{}.