Play 2.0 中文资料 - HTTP 路由

内建的 HTTP 路由器

路由器组件掌管把传入的 HTTP 请求转发到 Action.

一个HTTP 请求可被 MVC 框架看成是一个事件. 这个事主要包含两方面的信息:

  • 请求路径 (如 /clients/1542, /photos/list), 包括查询字符串
  • HTTP 方法 (像 GET, POST, …).

路由定义在 conf/routes 文件中, 它会被编译. 这表明你可以直接在浏览器上看到路由错误信息:

路由文件的语法

conf/routes 是路由器的配置文件. 这个文件列出了应用所需的所有路由. 每条路由由 HTTP 方法和 URI 模式构成, 它们和一个 Action 发生器的调用相关联.

让我们来看看路由定义是什么样子:

路由以 HTTP 方法开始, 后面跟着 URI. 最后的元素是调用定义.

你还可以在路由文件中以 # 字符开头添加注释.

HTTP 方法

HTTP 方法可以另何被 HTTP 支持的有效方法 (GET, POST, PUT, DELETE, HEAD).

URI 模式

URI 模式定义了路由的请求路径. 请求路径的部分可以是动态的.

静态路径

例如, 为精确的匹配传入的 GET /clients/all 请求, 你要这么定义路由:

动态部分

如果你想要定义一个接收客户端 ID 的路由, 你需要添加动态的部分:

注: 一个 URI 模式可能有不止一个动态的部分.

动态部分默认的匹配策略用正则表达式写的话是 [^/]+, 这意味着任何定义为 :id 的动态部分只会精确的匹配一个 URI 部分.

Unmi 注: 这个模式  /clients/:id 意味着 id 值从 /clients/ 到下一个 / 斜杠之间的字符串,把上面的模式里的 id 类型改为字符串来测试一下:

然后对应的 controllers.Application.show(id: String) 实现如下:

当访问的 URL 是 http://localhost/clients/100-abc 时,页面显示 It works! id: 100-abc

当访问的 URL 是 http://localhost/clients/100abc/ 时,页面显示为:

从上图中可看出 routes 文件被转换后的结果,/clients/:id 就成了 /clients/$id<[^/]+,也就是 $id 变量取的是它后面尖括号里的正则表达式 [/]+ 代表的部分。

这儿还有一点与 Play 1.x 的 routes 不同的是,Play 1.x 中的 controllers 默认的包省略掉,Play 2.x 中不能省,即 Play 1.x 中可写成:

动态部分跨越多个 /

如果你想要一个动态部分能捕获多个以斜杠 "/" 分开的URI 路径段, 你可以用 *id 的语法定义一个动态部分, 它用了 .* 正则表达式:

这样如果请求是 GET /files/images/logo.png, name 的动态部分捕获到的值就是 images/logo.png value.

Unmi 注: 比如前面那个路由写成:

那么访问 URL  http://localhost/clients/100/abc 时,页面显示 It works! id: 100/abc,就是说斜杠也阻断不了 id。

动态部分使用自定义的正则表达式

你可以用自己的正则表达式来定义动态的部分, 语法是 $id<regex> :

Unmi 注: 其实前面的 :id 还是 *name 都会被 Play 转换成正则表达式的形式,如:

:id          转换成    $id<[^/]>+
*name   转换成    $name<.+>

指定到 Action 发生器方法的调用

路由定义的最后部分是方法调用. 这一部分必须定义对返回值为 play.api.mvc.Action 类型的有效的方法调用, 很典型的说就是一个 Controller 的 Action 方法.

如果方法没有定义参数, 只需给出方法的全限名称(Unmi 注: 其实这时候,方法后的空括号也可以省去,写成 controllers.Application.homePage):

如果 Action 方法定义了参数, 所有的参数都要能从请求的 URI 上搜寻到, 可以是从 URI 路径本身上抽取到,或是从查询字符串上抽取.

或者:

这是定义在 controllers.Application Controller 中对应的 show 方法:

参数类型

如果参数是 String 类型, 那么参数的指定的可选的. 假如你想 Play 转换传入的参数为某种指定的 Scala 类型, 你可以显式的指定参数的类型:

同时对应的 show 方法, 在controllers.Clients Controller 中的定义如下:

固定值参数

有时候你想要使用一个固定的值作为参数:

默认值参数

你也可以给参数提供一个默认值, 当在传入的请求中未找到值时就使用默认值:

路由优先级

多个路由可能会匹配到同一个请求. 如果存在冲突时, 第一个路由 (依定义的顺序) 将被采用.

反向路由

路由也会被用于在 Scala 调用中产生一个 URL. 这使得在一个配置文件中中心化你的 URI 模式成为可能, 因此你可以在重构建应用的时候更充满自信.

对于 routes 文件中定义的每一 Controller, 路由器都会在路由包中产生一个 ‘反向 Controller’, 它具相同的 Action 方法, 相同的签名, 但是返回值类型是 play.api.mvc.Call,而不是 play.api.mvc.Action 类型.

play.api.mvc.Call 定义了一个 HTTP 调用, 并提供了 HTTP 方法和 URI.

例如, 你要是创建一个如下的 Controller:

同时若你在 conf/routes 文件中的映射是:

你可以通过 hello Action 方法反向得到 URL, 需要使用到 controllers.routes.Application 反向 Controller:

类别: PlayFramework. 标签: , , . 阅读(1,273). 订阅评论. TrackBack.

Leave a Reply

Be the First to Comment!

avatar