§處理錯誤
HTTP 應用程式可以傳回兩種主要類型的錯誤 - 伺服器端錯誤和用戶端錯誤。用戶端錯誤表示連線的用戶端做錯了某些事,伺服器端錯誤表示伺服器端出了問題。
在許多情況下,Play 會自動偵測用戶端錯誤 - 這些錯誤包括格式錯誤的標頭值、不支援的內容類型,以及對找不到的資源提出的要求。在許多情況下,Play 也會自動處理伺服器端錯誤 - 如果您的動作程式碼擲回例外,Play 會擷取此例外並產生伺服器端錯誤頁面傳送給用戶端。
Play 處理這些錯誤的介面是 HttpErrorHandler
。它定義了兩個方法,onClientError
和 onServerError
。
§處理 JSON API 中的錯誤
預設情況下,Play 會以 HTML 格式傳回錯誤。
對於 JSON API,以 JSON 格式傳回錯誤會更一致。
Play 提出了另一個 HttpErrorHandler
實作,稱為 JsonHttpErrorHandler
,它會傳回以 JSON 格式化的錯誤。
若要使用該 HttpErrorHandler
實作,您應該在 application.conf
中設定 play.http.errorHandler
設定屬性,如下所示
play.http.errorHandler = play.http.JsonHttpErrorHandler
§同時使用 HTML 和 JSON,以及其他內容類型
如果您的應用程式同時使用 HTML 和 JSON,這在現代網路應用程式中很常見,Play 提供另一個錯誤處理常式,它會根據客戶端 Accept
標頭中指定的偏好設定,委派給 HTML 或 JSON 錯誤處理常式。這可以用以下方式指定
play.http.errorHandler = play.http.HtmlOrJsonHttpErrorHandler
這是大多數應用程式的合適錯誤處理常式預設選項。
最後,如果您想要支援除了 HTML 和 JSON 之外的其他錯誤內容類型,您可以延伸 PreferredMediaTypeHttpErrorHandler
,並針對特定內容類型新增錯誤處理常式,然後指定自訂錯誤處理常式,如下所述。
§提供自訂錯誤處理常式
如果您使用 BuiltInComponents
來建構您的應用程式,請覆寫 httpRequestHandler
方法以傳回您的自訂處理常式的執行個體。
如果您使用執行時期依賴注入(例如 Guice),則可以在執行時期動態載入錯誤處理常式。最簡單的方式是在根目錄中建立一個名為 ErrorHandler
的類別,實作 HttpErrorHandler
,例如
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.Singleton;
import play.http.HttpErrorHandler;
import play.mvc.*;
import play.mvc.Http.*;
@Singleton
public class ErrorHandler implements HttpErrorHandler {
public CompletionStage<Result> onClientError(
RequestHeader request, int statusCode, String message) {
return CompletableFuture.completedFuture(
Results.status(statusCode, "A client error occurred: " + message));
}
public CompletionStage<Result> onServerError(RequestHeader request, Throwable exception) {
return CompletableFuture.completedFuture(
Results.internalServerError("A server error occurred: " + exception.getMessage()));
}
}
如果您不想要將錯誤處理常式放在根目錄中,或者您想要針對不同的環境設定不同的錯誤處理常式,您可以透過設定 application.conf
中的 play.http.errorHandler
設定屬性來執行此操作
play.http.errorHandler = "com.example.ErrorHandler"
§擴充預設錯誤處理常式
Play 的預設錯誤處理常式提供許多有用的功能。例如,在開發模式中,當伺服器錯誤發生時,Play 會嘗試尋找並呈現應用程式中導致該例外狀況的程式碼片段,以便您可以快速查看並找出問題。您可能想要在生產環境中提供自訂伺服器錯誤,同時在開發環境中維持該功能。為了簡化這個過程,Play 提供一個 DefaultHttpErrorHandler
,其中有一些方便的方法,您可以覆寫這些方法,以便將自訂邏輯與 Play 現有的行為混合在一起。
例如,只要在生產環境中提供自訂伺服器錯誤訊息,讓開發錯誤訊息保持不變,而且您還想要提供特定的禁止錯誤頁面
import com.typesafe.config.Config;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.*;
import play.*;
import play.api.OptionalSourceMapper;
import play.api.UsefulException;
import play.api.routing.Router;
import play.http.DefaultHttpErrorHandler;
import play.mvc.*;
import play.mvc.Http.*;
@Singleton
public class ErrorHandler extends DefaultHttpErrorHandler {
@Inject
public ErrorHandler(
Config config,
Environment environment,
OptionalSourceMapper sourceMapper,
Provider<Router> routes) {
super(config, environment, sourceMapper, routes);
}
protected CompletionStage<Result> onProdServerError(
RequestHeader request, UsefulException exception) {
return CompletableFuture.completedFuture(
Results.internalServerError("A server error occurred: " + exception.getMessage()));
}
protected CompletionStage<Result> onForbidden(RequestHeader request, String message) {
return CompletableFuture.completedFuture(
Results.forbidden("You're not allowed to access this resource."));
}
}
查看 DefaultHttpErrorHandler
的完整 API 文件,以查看有哪些方法可以覆寫,以及如何利用它們。
下一步:測試您的應用程式
在這個文件中發現錯誤?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件指南 後,請隨時提交拉取請求。有問題或建議想要分享?請前往 我們的社群論壇 與社群展開對話。