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 にある生成されたソース ファイルから派生したものです。実際には、独自のソース ジェネレーターを追加して、routes ファイルを自分で解析することもできますが、リフレクションを使用する方が簡単だと思います。

さらにやりたいことは、不要なメソッドを除外することです。これにより、すべてのルート (javascriptRouter 自体を含む) が得られるからです。

于 2012-08-19T07:41:14.993 に答える
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

Play 2.4 Java に対する @rochb の回答を拡張します。パッケージ名はわずかに異なり、複数のコントローラー パッケージがサポートされています。

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 に答える