目前,我定义我的应用程序的JavaScript路由器在一个相当冗长的方式
def javascriptRoutes = Action { implicit request =>
import routes.javascript._
Ok(Routes.javascriptRouter("jsRoutes")(
Login.method1,Login.Method2,
OtherController.method1,OtherController.method2,
//[...]
)).as("text/javascript")
}
我真正希望做的是创造一个javascriptRouter
所有的路由的routes
文件,所以我不必手动更新javascriptRoutes
每个我添加一个新的控制器方法的时间定义。
有没有办法去完成这个任务,还是说没有定义的略少冗长的方式javascriptRouter
?
您可以通过像这样反射做到这一点:
val routeCache = {
import routes._
val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields().map(_.get(null))
controllers.flatMap { controller =>
controller.getClass().getDeclaredMethods().map { action =>
action.invoke(controller).asInstanceOf[play.core.Router.JavascriptReverseRoute]
}
}
}
def javascriptRoutes = Action { implicit request =>
Ok(Routes.javascriptRouter("jsRoutes")(routeCache:_*)).as("text/javascript")
}
这是从在靶/阶-2.xx的/ src_managed发现生成的源文件的。 其实你可以添加自己的源发生器和分析路由文件了,但我觉得通过反射更容易做。
你可能想要做的另外一点是过滤掉你不想要的方式,因为这会给你的所有路由(包括javascriptRouter本身)。
此外,如果您使用的播放2.4,有些类/包已被更改:
def javascriptRoutes = Action { implicit request =>
Ok(play.api.routing.JavaScriptReverseRouter("jsRoutes")(routeCache:_*)).as("text/javascript")
}
val routeCache: Array[JavaScriptReverseRoute] = {
import routes._
val jsRoutesClass: Class[javascript] = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))
val met = for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods if method.getReturnType == classOf[play.api.routing.JavaScriptReverseRoute]
) yield method.invoke(controller).asInstanceOf[play.api.routing.JavaScriptReverseRoute]
met
}
我需要在Java中。 在此情况下复制它,它是使用了别人的。
public static Result javascriptRoutes() throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
// use reflection to get the fields of controllers.routes.javascript
Set<Object> reverseRoutes = new HashSet<Object>();
for (Field f : controllers.routes.javascript.class.getFields()) {
// get its methods
for (Method m : getAllMethods(f.getType(), withReturnType(JavascriptReverseRoute.class))) {
// for each method, add its result to the reverseRoutes
reverseRoutes.add(m.invoke(f.get(null)));
}
}
// return the reverse routes
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("jsRoutes",
reverseRoutes.toArray(new JavascriptReverseRoute[reverseRoutes.size()])));
}
通过thatsmydoing很不错的解决方案。 如果你有在某些其他子包的JavaScript的路线,你需要声明routeCache这样
val routeCache = {
val jsRoutesClass = classOf[controllers.api.routes.javascript]
val controllerArray = jsRoutesClass.getFields().map(_.get(null))
controllerArray.flatMap { controller =>
controller.getClass().getDeclaredMethods().map { action =>
action.invoke(controller).asInstanceOf[play.core.Router.JavascriptReverseRoute]
}
}
}
扩大@ rochb的答案玩2.4的Java,其中包名称略有不同,与多个控制器包的支持。
public Result javascriptRoutes() throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
// use reflection to get the fields of controllers.routes.javascript and other controller packages
Set<Object> reverseRoutes = new HashSet<Object>();
Class[] routeClasses = {controllers.routes.javascript.class, com.example.package1.routes.javascript.class, com.example.package2.routes.javascript.class};
for (int i = 0; i < routeClasses.length; i++) {
for (Field f : routeClasses[i].getFields()) {
// get its methods
for (Method m : getAllMethods(f.getType(), withReturnType(play.api.routing.JavaScriptReverseRoute.class))) {
// for each method, add its result to the reverseRoutes
reverseRoutes.add(m.invoke(f.get(null)));
}
}
}
// return the reverse routes
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("jsRoutes",
reverseRoutes.toArray(new play.api.routing.JavaScriptReverseRoute[reverseRoutes.size()])));
}