§路由 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 方法,例如 POST
、PUT
和 DELETE
。
注意:重要的是要注意,在使用 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();
支持的类型包括 Integer
、Long
、Float
、Double
、Boolean
以及扩展 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
在应用程序加载器中提供路由器,以使用自定义路由器绑定或模块覆盖,如 绑定和模块 中所述。
下一步:自定义绑定
在此文档中发现错误?此页面的源代码可以在 此处 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?访问 我们的社区论坛,与社区开始对话。