生成播放2的JavaScript路由器的更简洁的方式(Less Verbose way of gen

2019-07-31 01:41发布

目前,我定义我的应用程序的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

Answer 1:

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

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本身)。



Answer 2:

此外,如果您使用的播放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
}


Answer 3:

我需要在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()])));
}


Answer 4:

通过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]
  }
 }
}


Answer 5:

扩大@ 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()])));
}


文章来源: Less Verbose way of generating Play 2's javascript router