文件

§路由 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 區段中,可以找到嵌入 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 提供,以使用自訂路由器繫結或模組覆寫,詳細資訊請參閱 繫結和模組

下一步:自訂繫結


在此文件發現錯誤?此頁面的原始程式碼可在 這裡 找到。在閱讀完 文件指南 後,請隨時提交拉取請求。有問題或建議要分享?請前往 我們的社群論壇 與社群展開討論。