在使用 Java 創(chuàng)建可靠的 REST API 時(shí),不僅需要對(duì) HTTP 請求和響應(yīng)有基本了解,還需確保 API 設(shè)計(jì)良好、可維護(hù)且安全。本文將提供四個(gè)關(guān)鍵技巧,以改進(jìn) REST API。假設(shè)已經(jīng)熟悉 Richardson 成熟度模型,尤其是達(dá)到 2 級(jí),這是良好 API 的最低要求。如需快速了解理查森成熟度模型,建議閱讀 Martin Fowler 的文章《理查森成熟度模型》。
在了解上述先決條件后,接下來將深入探討這些技巧。為便于說明,以下示例來自探險(xiǎn)領(lǐng)域。盡管不會(huì)詳細(xì)探討實(shí)體和層,但假設(shè)存在以下實(shí)體類:
public class Expedition { private String name; private String location; private LocalDate date; public Expedition(String name, String location, LocalDate date) { this.name = name; this.location = location; this.date = date; } public String getName() { return name; } public String getLocation() { return location; } public LocalDate getDate() { return date; }}
設(shè)計(jì)良好的 REST API 的關(guān)鍵之一是確保術(shù)語的一致性,并仔細(xì)關(guān)注服務(wù)的詞匯。首先應(yīng)遵循通用命名約定,然后再向更具體的術(shù)語細(xì)化。可以借助領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)原則,從主域出發(fā),逐步細(xì)化到子域。
一個(gè)簡單的經(jīng)驗(yàn)法則是使用復(fù)數(shù)名詞表示資源,例如:
示例代碼:
@Path("expeditions")public class ExpeditionResource { @GET public List<Expedition> list() { // 實(shí)現(xiàn)代碼 } @GET @Path("/{id}") public Expedition get(@PathParam("id") String id) { // 實(shí)現(xiàn)代碼 } @GET @Path("/search") public List<Expedition> mine() { // 實(shí)現(xiàn)代碼 }}
有關(guān)保持一致性的更詳細(xì)指南,請參考《REST API 設(shè)計(jì)規(guī)則手冊》。
隨著 API 的復(fù)雜性不斷增加,維護(hù)和擴(kuò)展變得至關(guān)重要。確保可維護(hù)性的一種有效方式是提供適當(dāng)?shù)奈臋n。盡管文檔可能不是許多開發(fā)人員最喜歡的任務(wù),但它是不可或缺的。OpenAPI 是一個(gè)優(yōu)秀的工具,能夠自動(dòng)生成和增強(qiáng)文檔。欲了解更多信息,請?jiān)L問 OpenAPI。
另一個(gè)關(guān)鍵方面是版本控制。版本控制可以確保向后兼容性,并實(shí)現(xiàn)不同 API 版本之間的平滑過渡。它允許同時(shí)支持新舊版本,從而鼓勵(lì)用戶在方便時(shí)遷移到最新版本。在 Java 中,可以通過為每個(gè)版本使用單獨(dú)的包構(gòu)建代碼,并創(chuàng)建適配器層來管理版本之間的交互,來實(shí)現(xiàn)這一點(diǎn)。
示例:
package os.expert.demo.expeditions.v1;@Path("/api/v1/expeditions")public class ExpeditionResource { // 實(shí)現(xiàn)代碼}package os.expert.demo.expeditions.v2;@Path("/api/v2/expeditions")public class ExpeditionResource { // 實(shí)現(xiàn)代碼}
安全性是任何 API 的基本組成部分。一般原則是永遠(yuǎn)不要信任用戶;始終驗(yàn)證其訪問所請求資源的權(quán)限。采用身份驗(yàn)證的方法,可以確定用戶可以訪問哪些探險(xiǎn),而無需依賴用戶提供的 ID。
@GET@Path("/my-expeditions")public List<Expedition> myExpeditions() { // 用戶已通過身份驗(yàn)證,無需請求 ID // 實(shí)現(xiàn)代碼}
這一原則同樣適用于編輯或刪除資源等其他操作。在繼續(xù)執(zhí)行之前,務(wù)必驗(yàn)證權(quán)限。
設(shè)計(jì)良好的 API 應(yīng)具備強(qiáng)大的異常處理機(jī)制,將錯(cuò)誤映射到正確的 HTTP 狀態(tài)代碼。例如,如果未找到探險(xiǎn),API 應(yīng)返回 404 Not Found 狀態(tài),以確保 Java 代碼與 REST API 語義之間的一致性。
@Providerpublic class ExpeditionNotFoundExceptionMapper implements ExceptionMapper<ExpeditionNotFoundException> { @Override public Response toResponse(ExpeditionNotFoundException exception) { return Response.status(Response.Status.NOT_FOUND) .entity(exception.getMessage()) .build(); }}
總之,創(chuàng)建可靠的 REST API 涉及幾個(gè)關(guān)鍵步驟:
通過遵循這些技巧,能夠順利地使用 Java 開發(fā)可靠且可維護(hù)的 REST API,即使是經(jīng)驗(yàn)豐富的開發(fā)人員也可能面臨這一挑戰(zhàn)。
原文鏈接:Four Essential Tips for Building a Robust REST API in Java