用过 PlayFramework 的都知道默认的路由器文件是 conf/routes,Play2 可以定义自己的 routes 文件。在默认的 application.conf 中有这么一段注释
# Router
# ~~~~~
# Define the Router object to use for this application.
# This router will be looked up first when the application is starting up,
# so make sure this is the entry point.
# Furthermore, it's assumed your route file is named properly.
# So for an application router likeconf/my.application.Router
,
# you may need to define a router filemy.application.routes
.
# Default to Routes in the root package (andconf/routes
)
# application.router=my.application.Routes
也就是通过 application.router 可以定义自己的 routes 文件。上面的解释很容易把人搞混,问题在于何处是文件路径,何处是类路径,至少写着的 'conf/my.applicaton.Router 就是在混淆视听。对于上面的解释要明白下面几点
1. application.router 指定的是路由器文件生成的类路径,在 target/scala-2.10/{classes,classes_managed,src_managed} 这三个目录中可以看到
2. 自定义的路由器文件必须以 .routes 为后缀,Play2 会自动编译 conf/ 下以 .routes 为后缀的或 routes 文件
3. 基于上面两条,Play2 不是根据 application.router 配置去加载路由配置文件,而是用以加载第二步生成的类
4. 路由配置文件的点分隔又会映射到 Routes 类的包名上去,因此路由文件名一定程度上又表现出了类路径的意义来,这里有点儿乱
严谨的说来,Play2 在 application.router=my.application.Routes 这个配置上把类路径和文件路径这两个概念搅和到一块去了,互为渗透。
所以即使在 application.conf 中没有配置 application.router,只要在 conf/ 目录中有 routes 或 .routes 文件就会被编译出 Routes 相关的类。因为我们的配置方案是这样的
1. 多包层次时
路由文件:my.applicaton.routes -- 以 .routes 为后缀,这样它就会编译出 my.application.Routes, my.application.Routes$ ... 等类出来
application.conf 配置: application.router=my.application.Routes -- 指定生成的主类
2. 单个包层次
路由文件:myapplication.routes -- 自定义的路由器文件总是要以 .routes 为后缀,编译出 myapplication.Routes 等来
application.conf 配置: application.router=myapplication.Routes 路由文件中有点就会有包
下图是把默认的 routes 改名为 my.application.routes(application.conf 中未开启 application.router), 然后执行 play compile
后生成的文件,并显示出 Play 怎么去加载 Routes 类的。
上面的 Application.class 告诉我们 Play 加载 Routes 是根据 application.router 配置的值连接上 $ 来,或直接命中 Routes$ 类。
my.application.routes 被编译生成的主类是 my.application.Routes,所以 application.router 中配置这个。
即使是可以定制自己的路由文件,但也不能有多个路由文件,因为 controllers/routes.java 只能有一个,在编译非第一个路由文件时会报错
ReverseApplication is already defined as class ReverseApplication
如果指定错了路由器类,出错类似
NoClassDefFoundError: my/application/routes$ (wrong name: my/application/Routes$)
如果把 routes 改了名,但 application.conf 没有配置 application.router,得到
Action not found
奇怪的是,明明不存在 routes,应该是找不到 Router$ 类才对
我们还可以在 routes-compiler 下找到 RoutesCompiler.scala,里面有片断
1 2 3 4 5 6 7 |
def compile(file: File, generatedDir: File, additionalImports: Seq[String], generateReverseRouter: Boolean = true, namespaceReverseRouter: Boolean = false) { val namespace = Option(Path(file).name).filter(_.endsWith(".routes")).map(_.dropRight(".routes".size)) val packageDir = namespace.map(pkg => new File(generatedDir, pkg.replace('.', '/'))).getOrElse(generatedDir) val generated = GeneratedSource(new File(packageDir, "routes_routing.scala")) ...... |
上面 endsWith(".routes") 判断,参照前部分来生成包结构,但是还没找到 Play 的哪段代码去编译 routes 文件的,这个可不是 .routes 为后缀的。
本文链接 https://yanbin.blog/play2-use-customized-routes-file/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。