日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Spark构建简单的RESTful API

發布時間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Spark构建简单的RESTful API 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

免責聲明 :這篇文章是關于名為Spark的Java微型Web框架的,而不是關于數據處理引擎Apache Spark的 。

在此博客文章中,我們將看到如何使用Spark構建簡單的Web服務。 如免責聲明中所述,Spark是受Ruby框架Sinatra啟發的Java微型Web框架。 Spark的目的是簡化操作,僅提供最少的功能集。 但是,它提供了用幾行Java代碼構建Web應用程序所需的一切。


入門

假設我們有一個帶有一些屬性的簡單域類和一個提供一些基本CRUD功能的服務:

public?class?User?{private?String?id;private?String?name;private?String?email;//?getter/setter }public?class?UserService?{//?returns?a?list?of?all?userspublic?List<User>?getAllUsers()?{?..?}//?returns?a?single?user?by?idpublic?User?getUser(String?id)?{?..?}//?creates?a?new?userpublic?User?createUser(String?name,?String?email)?{?..?}//?updates?an?existing?userpublic?User?updateUser(String?id,?String?name,?String?email)?{?..?} }

現在,我們希望將UserService的功能公開為RESTful API(為簡單起見,我們將跳過REST的超媒體部分)。 為了訪問,創建和更新用戶對象,我們要使用以下URL模式:

得到 /用戶 獲取所有用戶的列表
得到 / users / <id> 獲取特定用戶
開機自檢 /用戶 創建一個新用戶
/ users / <id> 更新用戶

返回的數據應為JSON格式。

要開始使用Spark,我們需要以下Maven依賴項:

<dependency><groupId>com.sparkjava</groupId><artifactId>spark-core</artifactId><version>2.0.0</version> </dependency> <dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.7</version> </dependency>

Spark使用SLF4J進行日志記錄,因此我們需要SLF4J活頁夾才能查看日志和錯誤消息。 在此示例中,我們為此目的使用slf4j-simple依賴項。 但是,您也可以使用Log4j或您喜歡的任何其他綁定程序。 在類路徑中使用slf4j-simple足以在控制臺中查看日志輸出。

我們還將使用GSON生成JSON輸出,并使用JUnit編寫簡單的集成測試。 您可以在完整的pom.xml中找到這些依賴項。

返回所有用戶

現在該創建一個負責處理傳入請求的類了。 我們首先實現GET / users請求,該請求應返回所有用戶的列表。

import?static?spark.Spark.*;public?class?UserController?{public?UserController(final?UserService?userService)?{get("/users",?new?Route()?{@Overridepublic?Object?handle(Request?request,?Response?response)?{//?process?requestreturn?userService.getAllUsers();}});//?more?routes} }

注意第一行中的spark.Spark。*的靜態導入。 這使我們可以訪問各種靜態方法,包括get(),post(),put()等。 在構造函數中,get()方法用于注冊一個Route,該Route偵聽/ users上的GET請求。 路由負責處理請求。 每當發出GET / users請求時,都會調用handle()方法。 在handle()內部,我們返回一個應發送給客戶端的對象(在本例中為所有用戶的列表)。

Spark從Java 8 Lambda表達式中受益匪淺。 Route是一個功能接口(僅包含一種方法),因此我們可以使用Java 8 Lambda表達式來實現它。 使用Lambda表達式,上面的Route定義如下所示:

get("/users",?(req,?res)?->?userService.getAllUsers());

要啟動該應用程序,我們必須創建一個簡單的main()方法。 在main()內部,我們創建服務的實例,并將其傳遞給我們新創建的UserController:

public?class?Main?{public?static?void?main(String[]?args)?{new?UserController(new?UserService());} }

如果現在運行main(),Spark將啟動一個偵聽端口4567的嵌入式Jetty服務器。我們可以通過啟動GET http:// localhost:4567 / users請求來測試我們的第一個路由。

如果服務返回包含兩個用戶對象的列表,則響應主體可能如下所示:

[com.mscharhag.sparkdemo.User@449c23fd,?com.mscharhag.sparkdemo.User@437b26fe]

顯然,這不是我們想要的回應。

Spark使用名為ResponseTransformer的接口將路由返回的對象轉換為實際的HTTP響應。
ReponseTransformer看起來像這樣:

public?interface?ResponseTransformer?{String?render(Object?model)?throws?Exception; }

ResponseTransformer具有一個方法,該方法接受一個對象并返回此對象的String表示形式。 ResponseTransformer的默認實現只是在傳遞的對象上調用toString()(它創建如上所示的輸出)。

由于我們要返回JSON,因此我們必須創建一個ResponseTransformer,將傳遞的對象轉換為JSON。 為此,我們使用帶有兩個靜態方法的小型JsonUtil類:

public?class?JsonUtil?{public?static?String?toJson(Object?object)?{return?new?Gson().toJson(object);}public?static?ResponseTransformer?json()?{return?JsonUtil::toJson;} }

toJson()是使用GSON將對象轉換為JSON的通用方法。 第二種方法利用Java 8方法引用來返回ResponseTransformer實例。 ResponseTransformer還是一個功能接口,因此可以通過提供適當的方法實現(toJson())來滿足它。 因此,每當調用json()時,我們都會獲得一個新的ResponseTransformer,它利用了我們的toJson()方法。

在我們的UserController中,我們可以將ResponseTransformer作為第三個參數傳遞給Spark的get()方法:

import?static?com.mscharhag.sparkdemo.JsonUtil.*;public?class?UserController?{public?UserController(final?UserService?userService)?{get("/users",?(req,?res)?->?userService.getAllUsers(),?json());...} }

再次注意第一行中JsonUtil。*的靜態導入。 這使我們可以選擇僅通過調用json()來創建新的ResponseTransformer。

現在,我們的響應如下所示:

[{"id":?"1866d959-4a52-4409-afc8-4f09896f38b2","name":?"john","email":?"john@foobar.com" },{"id":?"90d965ad-5bdf-455d-9808-c38b72a5181a","name":?"anna","email":?"anna@foobar.com" }]

我們還有一個小問題。 返回的響應帶有錯誤的Content-Type 。 為了解決這個問題,我們可以注冊一個設置JSON Content-Type的Filter:

after((req,?res)?->?{res.type("application/json"); });

過濾器還是一個功能接口,因此可以通過一個簡短的Lambda表達式實現。 在我們的Route處理完請求后,過濾器會將每個響應的Content-Type更改為application / json。 我們還可以使用before()代替after()來注冊過濾器。 然后,在路由處理請求之前,將調用過濾器。

GET / users請求現在應該可以工作了!

返回特定用戶

要返回特定用戶,我們只需在UserController中創建一條新路由:

get("/users/:id",?(req,?res)?->?{String?id?=?req.params(":id");User?user?=?userService.getUser(id);if?(user?!=?null)?{return?user;}res.status(400);return?new?ResponseError("No?user?with?id?'%s'?found",?id); },?json());

使用req.params(“:id”),我們可以從URL獲取:id路徑參數。 我們將此參數傳遞給我們的服務以獲取相應的用戶對象。 如果未找到具有傳遞ID的用戶,則假定服務返回null。 在這種情況下,我們將HTTP狀態代碼更改為400(錯誤請求)并返回一個錯誤對象。

ResponseError是一個小的幫助程序類,我們用于將錯誤消息和異常轉換為JSON。 看起來像這樣:

public?class?ResponseError?{private?String?message;public?ResponseError(String?message,?String...?args)?{this.message?=?String.format(message,?args);}public?ResponseError(Exception?e)?{this.message?=?e.getMessage();}public?String?getMessage()?{return?this.message;} }

現在,我們可以使用以下請求查詢單個用戶:

GET / users / 5f45a4ff-35a7-47e8-b731-4339c84962be

如果存在具有此ID的用戶,我們將收到如下所示的響應:

{"id":?"5f45a4ff-35a7-47e8-b731-4339c84962be","name":?"john","email":?"john@foobar.com" }

如果我們使用無效的用戶ID,將創建ResponseError對象并將其轉換為JSON。 在這種情況下,響應如下所示:

{"message":?"No?user?with?id?'foo'?found" }

創建和更新用戶

創建和更新用戶非常容易。 就像返回所有用戶的列表一樣,這是通過單個服務調用完成的:

post("/users",?(req,?res)?->?userService.createUser(req.queryParams("name"),req.queryParams("email") ),?json());put("/users/:id",?(req,?res)?->?userService.updateUser(req.params(":id"),req.queryParams("name"),req.queryParams("email") ),?json());

要為HTTP POST或PUT請求注冊路由,我們只需使用Spark的靜態post()和put()方法。 在Route內部,我們可以使用req.queryParams()訪問HTTP POST參數。

為了簡單起見(并顯示另一個Spark功能),我們不在路由內進行任何驗證。 相反,我們假定如果傳入無效值,則服務將引發IllegalArgumentException。

Spark為我們提供了注冊ExceptionHandlers的選項。 如果在處理路由時引發Exception,則將調用ExceptionHandler。 ExceptionHandler是我們可以使用Java 8 Lambda表達式實現的另一個單一方法接口:

exception(IllegalArgumentException.class,?(e,?req,?res)?->?{res.status(400);res.body(toJson(new?ResponseError(e))); });

在這里,我們創建一個ExceptionHandler,如果拋出IllegalArgumentException則調用它。 捕獲的Exception對象作為第一個參數傳遞。 我們將響應代碼設置為400,并在響應正文中添加一條錯誤消息。

如果當email參數為空時服務拋出IllegalArgumentException,我們可能會收到如下響應:

{"message":?"Parameter?'email'?cannot?be?empty" }

控制器的完整資源可以在這里找到。

測試中

由于Spark的簡單性質,因此為示例應用程序編寫集成測試非常容易。

讓我們從基本的JUnit測試設置開始:

public?class?UserControllerIntegrationTest?{@BeforeClasspublic?static?void?beforeClass()?{Main.main(null);}@AfterClasspublic?static?void?afterClass()?{Spark.stop();}... }

在beforeClass()中,我們通過簡單地運行main()方法來啟動應用程序。 所有測試完成后,我們調用Spark.stop()。 這將停止運行我們的應用程序的嵌入式服務器。

之后,我們可以在測試方法中發送HTTP請求,并驗證我們的應用程序返回了正確的響應。 一個發送創建新用戶請求的簡單測試如下所示:

@Test public?void?aNewUserShouldBeCreated()?{TestResponse?res?=?request("POST",?"/users?name=john&email=john@foobar.com");Map<String,?String>?json?=?res.json();assertEquals(200,?res.status);assertEquals("john",?json.get("name"));assertEquals("john@foobar.com",?json.get("email"));assertNotNull(json.get("id")); }

request()和TestResponse是兩個小型的自制測試實用程序。 request()將HTTP請求發送到傳遞的URL,并返回TestResponse實例。 TestResponse只是一些HTTP響應數據的小包裝。 request()和TestResponse的源包含在GitHub上的完整測試類中 。

結論

與其他Web框架相比,Spark僅提供了少量功能。 但是,它是如此簡單,您可以在幾分鐘之內構建小型Web應用程序(即使您以前從未使用過Spark)。 如果您想研究Spark,則應該清楚地使用Java 8,它減少了您必須編寫的代碼量。

  • 您可以在GitHub上找到示例項目的完整源代碼。

翻譯自: https://www.javacodegeeks.com/2014/06/building-a-simple-restful-api-with-spark.html

總結

以上是生活随笔為你收集整理的使用Spark构建简单的RESTful API的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。