Меньше подробный способ создания Play 2 javascript router
В настоящее время я определяю свой 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
?
Ответы
Ответ 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")
}
Это было получено из сгенерированных исходных файлов, найденных в target/ scala -2.x.x/src_managed. Вы действительно можете добавить свой собственный генератор источников и самостоятельно проанализировать файл маршрутов, но я нахожу, что я делаю это через отражение легче.
Дополнительная вещь, которую вы, возможно, захотите сделать, - это отфильтровать методы, которые вы не хотите, поскольку это даст вам ВСЕ маршруты (включая сам javascriptRouter).
Ответ 2
Кроме того, если вы используете 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
}
Ответ 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()])));
}
Ответ 4
Очень приятное решение этой проблемы. Если у вас есть 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]
}
}
}
Ответ 5
Расширение ответа @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()])));
}