我们用 Playframework 2 时,当 routes 中太多的路由配置时,我们可能会考虑把它们归类分布到多个文件中去。比如按 API 或用途分,有些是 RESTful API,有些是 Web 页面的,对于这种情景,我们可以由以下几个文件来组织:
1. routes 文件,这个仍然是充当入口
1 2 3 |
-> / general.Routes -> /api api.Routes -> /web web.Routes |
这里穿插着来解释下,->
是固定写法,表示要去别外寻找了,紧接着的 /, /api, 和 /web 是分类路由的上下文了,例如,访问 api.routes 中定义的 /customers 的完整 API 路径就是 /test/customers。最后一部分是全类名,并非指别的路由文件的名称,像文件 general.routes 编译后会生成 general 包下生成 Routes.scala 文件,即类为 general.Routes.
2. general.routes
1 2 |
GET /index controllers.Application.index() GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) |
像前面在 routes 文件中是直接用 -> / general.Routes
来引用 general.routes 文件的,上下文 / 并不会改变 general.routes 中路由的访问方式,所以我们可以把 general.routes 中的内容搬移到 routes 文件中。
3. api.routes
1 |
GET /customers controllers.CustomersController.index() |
4. web.routes
1 |
GET /customers controllers.CustomersController.listPage() |
路由文件全分配到位,我们运行 activator compile 看下生成了什么,就是下面这张图
从上面那张图我们明明白白的知道,general.routes, api.routes 和 web.routes 都产生出相应的包名,类都是 Routes。
如果上面做下来你没有遇到编译错误的话,那你算是幸运的,我所遇到的错误是
[error] /Users/yanbin/Desktop/playtest/app/views/main.scala.html:8: value Assets is not a member of object controllers.routes
[error] <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
[error] ^
[error] /Users/yanbin/Desktop/playtest/app/views/main.scala.html:9: value Assets is not a member of object controllers.routes
[error] <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
[error] ^
[error] /Users/yanbin/Desktop/playtest/app/views/main.scala.html:10: value Assets is not a member of object controllers.routes
[error] <script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script>
[error] ^
我当时也是半天摸不着头脑,后来发现错误中的 @routes.Assets 本该是定义在 target/scala-2.11/routes/main/controllers/routes.java 中的
public static final controllers.ReverseAssets Assets .....
这个文件注释中也告诉了我们该文件怎么产生的,例如本例中是
// @GENERATOR:play-routes-compiler
// @SOURCE:/Users/yanbin/Desktop/playtest/conf/web.routes
// @DATE:Mon Feb 22 23:05:47 CST 2016
如果不拆分 routes 文件的话,上面指示的 @SOURCE 应该就是 /Users/yanbin/Desktop/playtest/conf/routes, 而 routes.java 中的 Assets 常量是由下面这行生成的
1 |
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) |
因此我们必须把这行写一份到 web.routes 文件中,重新编译就可以通过了。
类似的,如果我们编译时碰到 @javascript.Assets........ 引用资源时的错误,解决方法也是一样的。
Playframework 的一位开发人员对此的解释是 https://github.com/playframework/playframework/issues/4430:
Does
api.routes
contain any routes to any controllers in thecontrollers
package? If so, then that's the reason, the reverse router fromapi.routes
for thecontrollers
package is overwriting the reverse router fromroutes
for thecontrollers
package, different routes files must address controllers in different packages.
其次,不妨留意下 @routes.Assets.versioned("stylesheets/main.css") 在不同情况下产生的全路径也是有有差异,但不影响使用。如可能是
/public/stylesheets/main.css 或 /web/public/stylesheets/main.css
Play 2 支持这样简单的把 routes 拆到多个文件中的做法好像是 2.3 开始提供的。记得我们刚开始升级到 Play 2 的时候,如果在 routes 文件中要写成
-> /web web.Routes
那还得为 web 建立一个 sbt 子项目,web.Routes 中用到的类都必须放在 web 子项目中,于是子项目之间,或子项目与主项目之间类相互间访问就成了一个大问题,这也就是为什么我们当时不得不把所有的东西堆在一个 routes 文件中。
参考:1. https://groups.google.com/d/msg/play-framework/dxDRml0khdY/92Sf48Fhs4MJ
博主,那个是vim吗?配色看着很好看。
是的,是 vim.
原来独立博客了
是的,你还见过我未独立的时候啊?