§路由 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 區段中,可以找到嵌入 Play 伺服器搭配路由 DSL 的範例。
§提供 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()]);
}
}
§覆寫繫結
路由器也可以使用應用程式載入器中的 e.g. GuiceApplicationBuilder
提供,以使用自訂路由器繫結或模組覆寫,詳細資訊請參閱 繫結和模組
下一步:自訂繫結
在此文件發現錯誤?此頁面的原始程式碼可在 這裡 找到。在閱讀完 文件指南 後,請隨時提交拉取請求。有問題或建議要分享?請前往 我們的社群論壇 與社群展開討論。