10

目前我以相当冗长的方式定义我的应用程序的 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

4

5 回答 5

17

你可以像这样通过反射来做到这一点:

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")
}

这是从 target/scala-2.xx/src_managed 中生成的源文件派生的。您实际上可以添加自己的源生成器并自己解析路由文件,但我发现通过反射更容易做到这一点。

您可能想要做的另一件事是过滤掉您不想要的方法,因为这将为您提供所有路由(包括 javascriptRouter 本身)。

于 2012-08-19T07:41:14.993 回答
3

此外,如果您使用的是 Play 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
}
于 2016-02-17T09:08:36.677 回答
2

我在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()])));
}
于 2015-05-28T13:40:18.227 回答
1

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]
  }
 }
}
于 2015-05-04T07:59:14.107 回答
1

扩展 @rochb 对 Play 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()])));
}
于 2015-07-20T05:50:36.547 回答