文档

§路由 DSL

Play 提供了一个直接在代码中使用的路由 DSL。此 DSL 有很多用途,包括嵌入轻量级 Play 服务器,为常规 Play 应用程序提供自定义或更高级的路由功能,以及模拟 REST 服务以进行测试。

DSL 使用类似于 Play 的编译路由文件的路径模式语法,提取参数并调用使用 lambda 实现的动作。

DSL 由 RoutingDsl 提供。由于您将实现动作,因此您可能希望从 Results 中导入静态方法,其中包括用于创建结果的工厂方法。DSL 使您可以访问当前的 Http.Request,并且您可以使用它来访问会话、cookie 等。因此,通常您至少需要以下导入

import javax.inject.Inject;

import play.api.mvc.AnyContent;
import play.api.mvc.BodyParser;
import play.api.mvc.PlayBodyParsers;
import play.mvc.Http;
import play.routing.Router;
import play.routing.RoutingDsl;
import java.util.concurrent.CompletableFuture;

import static play.mvc.Controller.*;

然后,您可以使用 依赖注入 获取 RoutingDsl 实例

public class MyComponent {

  private final RoutingDsl routingDsl;

  @Inject
  public MyComponent(RoutingDsl routing) {
    this.routingDsl = routing;
  }
}

或者,您可以直接创建一个新实例

RoutingDsl routingDsl = new RoutingDsl(bodyParser);

DSL 使用的一个简单示例是

Router router =
    routingDsl.GET("/hello/:to").routingTo((request, to) -> ok("Hello " + to)).build();

操作块的第一个参数是 Http.Request。然后提取 :to 参数并将其作为第一个参数传递给路由器。请注意,您在路径模式中为参数指定的名称无关紧要,重要的是路径中的参数与 lambda 中的参数顺序相同。路径模式中可以有 0 到 3 个参数,并且支持其他 HTTP 方法,例如 POSTPUTDELETE

注意:重要的是要注意,在使用 DSL 时,第一个参数始终是 Http.Request。接下来的参数是您在路由模式中实际声明的参数。

与 Play 的编译路由器一样,DSL 也支持匹配多路径段参数,这可以通过在参数前添加 * 来实现。

Router router =
    routingDsl.GET("/assets/*file").routingTo((request, file) -> ok("Serving " + file)).build();

正则表达式也受支持,通过在参数前添加 $ 并将参数后缀为带尖括号的正则表达式来实现。

Router router =
    routingDsl
        .GET("/api/items/$id<[0-9]+>")
        .routingTo((request, id) -> ok("Getting item " + id))
        .build();

在上面的示例中,lambda 中参数的类型未声明,Java 编译器将其默认为 Object。在这种情况下,路由 DSL 将参数作为 String 传递,但是如果您在参数上定义了显式类型,路由 DSL 将尝试将参数绑定到该类型。

Router router =
    routingDsl
        .GET("/api/items/:id")
        .routingTo((Http.Request request, Integer id) -> ok("Getting item " + id))
        .build();

支持的类型包括 IntegerLongFloatDoubleBoolean 以及扩展 PathBindable 的任何类型。

当然也支持异步操作,使用 routingAsync 方法。

Router router =
    routingDsl
        .GET("/api/items/:id")
        .routingAsync(
            (Http.Request request, Integer id) ->
                CompletableFuture.completedFuture(ok("Getting item " + id)))
        .build();

§绑定路由 DSL

根据用例,可以通过多种方式配置应用程序以使用路由 DSL。

§嵌入 Play

嵌入 Play 部分中可以找到使用路由 DSL 嵌入 Play 服务器的示例。

§提供 DI 路由器

可以使用与 应用程序入口点提供路由器 中详细介绍的类似方式将路由器提供给应用程序,例如使用 Java 构建器类和应用程序加载器。

public class AppLoader implements ApplicationLoader {
  public Application load(ApplicationLoader.Context context) {
    return new MyComponents(context).application();
  }
}

class MyComponents extends RoutingDslComponentsFromContext
    implements play.filters.components.NoHttpFiltersComponents {

  MyComponents(ApplicationLoader.Context context) {
    super(context);
  }

  @Override
  public Router router() {
    return routingDsl().GET("/hello/:to").routingTo((request, to) -> ok("Hello " + to)).build();
  }
}

§使用 Guice 提供 DI 路由器

可以使用以下代码片段通过 Guice 提供路由器。

@Singleton
public class GuiceRouterProvider implements Provider<play.api.routing.Router> {

  private final RoutingDsl routingDsl;

  @Inject
  public GuiceRouterProvider(RoutingDsl routingDsl) {
    this.routingDsl = routingDsl;
  }

  @Override
  public play.api.routing.Router get() {
    return routingDsl
        .GET("/hello/:to")
        .routingTo((request, to) -> ok("Hello " + to))
        .build()
        .asScala();
  }
}

在应用程序加载器中。

public class GuiceAppLoader extends GuiceApplicationLoader {

  @Override
  protected GuiceableModule[] overrides(ApplicationLoader.Context context) {
    GuiceableModule[] modules = super.overrides(context);
    GuiceableModule module =
        GuiceableModule$.MODULE$.fromPlayBinding(
            new BindingKey<>(play.api.routing.Router.class)
                .toProvider(GuiceRouterProvider.class)
                .eagerly());

    List<GuiceableModule> copyModules = new ArrayList<>(Arrays.asList(modules));
    copyModules.add(module);

    return copyModules.toArray(new GuiceableModule[copyModules.size()]);
  }
}

§覆盖绑定

还可以使用例如 GuiceApplicationBuilder 在应用程序加载器中提供路由器,以使用自定义路由器绑定或模块覆盖,如 绑定和模块 中所述。

下一步:自定义绑定


在此文档中发现错误?此页面的源代码可以在 此处 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?访问 我们的社区论坛,与社区开始对话。