§攔截 HTTP 要求
Play 的 Java API 提供兩種攔截動作呼叫的方式。第一種稱為 ActionCreator
,它提供一個 createAction
方法,用於建立動作組合中使用的初始動作。它會處理呼叫動作的實際方法,這允許您攔截請求。
第二種方式是實作您自己的 HttpRequestHandler
,這是 Play 中所有 HTTP 請求的主要進入點。這包括來自 Java 和 Scala 動作的請求。
§動作建立器
ActionCreator
介面有兩個可以實作的方法
createAction
:取得請求和與傳遞請求相關聯的控制器動作方法。動作可以是第一個或最後一個動作,具體取決於設定play.http.actionComposition.executeActionCreatorActionFirst
。wrapAction
:取得要執行的動作,並允許將最後一個全域攔截器新增到動作中。此方法已棄用,因為可以使用createAction
和上述設定來達成相同的目的。
還有一個 DefaultActionCreator
介面,您可以使用預設實作來延伸它。
注意:如果您正在實作自訂 ActionCreator,因為您需要在執行動作之前對動作套用橫切關注,建立 篩選器 是達成相同目的的更慣用的方式。
可以透過在根目錄套件中建立一個名為 ActionCreator
的類別來提供自訂動作建立器,該類別實作 play.http.ActionCreator
,例如
import java.lang.reflect.Method;
import java.util.concurrent.CompletionStage;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
public class ActionCreator implements play.http.ActionCreator {
@Override
public Action createAction(Http.Request request, Method actionMethod) {
return new Action.Simple() {
@Override
public CompletionStage<Result> call(Http.Request req) {
return delegate.call(req);
}
};
}
}
如果您不想將此類別放在根目錄套件中,或者您想要能夠針對不同的環境設定不同的動作處理常式,您可以透過在 application.conf
中設定 play.http.actionCreator
設定屬性來執行此操作
play.http.actionCreator = "com.example.MyActionCreator"
注意:如果您也正在使用 動作組合,則預設情況下,
createAction
方法傳回的動作會在動作組合動作之後執行。如果您想要變更此順序,請在application.conf
中設定play.http.actionComposition.executeActionCreatorActionFirst = true
。
§HTTP 請求處理常式
有時候應用程式會有更進階的需求,無法透過 Play 的抽象化來滿足。當發生這種情況時,應用程式可以提供 Play 最低層級 HTTP 管線 API 的自訂實作,也就是 HttpRequestHandler
。
提供自訂的 HttpRequestHandler
應當是最後的手段。大多數自訂需求都可以透過實作自訂路由器或 篩選器 來滿足。
§實作自訂請求處理常式
HttpRequestHandler
介面有一個方法必須實作,也就是 handlerForRequest
。這會取得請求以取得處理常式,並傳回一個包含 RequestHeader
和 Handler
的 HandlerForRequest
實例。
傳回請求標頭的原因是為了讓資訊(例如路由資訊)可以新增到請求中。透過這種方式,路由器可以標記請求並加上路由資訊,例如哪個路由與請求相符,這對於監控或甚至注入橫切功能很有用。
一個非常簡單的請求處理常式,僅委派給路由器,可能如下所示
import javax.inject.Inject;
import play.api.mvc.Handler;
import play.core.j.JavaHandler;
import play.core.j.JavaHandlerComponents;
import play.http.*;
import play.libs.streams.Accumulator;
import play.mvc.*;
import play.routing.Router;
public class SimpleHttpRequestHandler implements HttpRequestHandler {
private final Router router;
private final JavaHandlerComponents handlerComponents;
@Inject
public SimpleHttpRequestHandler(Router router, JavaHandlerComponents components) {
this.router = router;
this.handlerComponents = components;
}
public HandlerForRequest handlerForRequest(Http.RequestHeader request) {
Handler handler =
router
.route(request)
.orElseGet(() -> EssentialAction.of(req -> Accumulator.done(Results.notFound())));
if (handler instanceof JavaHandler) {
handler = ((JavaHandler) handler).withComponents(handlerComponents);
}
return new HandlerForRequest(request, handler);
}
}
請注意,我們需要注入 JavaHandlerComponents
並呼叫 handler.withComponents
以取得 Java 處理常式。這是 Java 動作運作的必要條件。如果您延伸 DefaultHttpRequestHandler
並呼叫 super.handlerForRequest()
,這也會自動為您處理。
請注意,HttpRequestHandler
目前有兩個具有預設實作的舊版方法,這些方法已移至 ActionCreator
。
§設定 http 要求處理程式
如果您使用 BuiltInComponents
來建構應用程式,請覆寫 httpRequestHandler
方法,以傳回自訂處理程式的執行個體。
如果您使用執行時期依賴性注入 (例如 Guice),可以在執行時期動態載入要求處理程式。最簡單的方法是在根目錄建立一個稱為 RequestHandler
的類別,並實作 HttpRequestHandler
。
如果您不想將要求處理程式放在根目錄,或者您想要能夠為不同的環境設定不同的要求處理程式,您可以透過設定 application.conf
中的 play.http.requestHandler
設定屬性來執行此操作
play.http.requestHandler = "com.example.RequestHandler"
下一步:非同步 HTTP 編寫程式
在此文件當中發現錯誤?此頁面的原始程式碼可在此處找到 here。在閱讀 文件指南 後,歡迎您貢獻一個 Pull Request。有問題或建議要分享?請前往 我們的社群論壇,與社群展開對話。