構建基於 Spark Java 框架的 API

REST
Remote
0
01:18 PM · Dec 01 ,2025

1. 簡介

在本文中,我們將對 Spark 框架 進行一個快速介紹。Spark 框架是受到 Ruby 的 Sinatra 框架啓發的快速開發 Web 框架,並基於 Java 8 Lambda 表達式的理念構建,使其比其他 Java 框架中編寫的應用程序更簡潔。

如果您想在 Java 中開發 Web API 或微服務時獲得 Node.js 般的體驗,那麼它是一個不錯的選擇。使用 Spark,您可以在少於十行代碼中構建一個 REST API,以便提供 JSON。

我們將通過一個“Hello World”示例進行快速入門,然後構建一個簡單的 REST API。

2. Maven 依賴項

2.1. Spark 框架

請在您的 pom.xml 中包含以下 Maven 依賴項:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.5.4</version>
</dependency>

您可以在 Maven 中央倉庫 中找到 Spark 的最新版本。

2.2. Gson 庫

在示例中的多個位置,我們將使用 Gson 庫進行 JSON 操作。 為了將 Gson 添加到您的項目,請在您的 pom.xml 中包含以下依賴項:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

您可以在 Maven 中央倉庫 中找到 Gson 的最新版本。

3. Getting Started With Spark Framework

讓我們來查看 Spark 應用程序的基本構建塊,並演示一個簡單的 Web 服務。

3.1. Routes

Spark Java 中的 Web 服務建立在 Routes 和它們的 handlers 之上。Routes 是 Spark 中的關鍵元素。根據 文檔,每個 Route 包含三個簡單的組成部分:一個 verb,一個 path,和一個 callback

  1. verb 是一個與 HTTP 方法相對應的方法。Verb 方法包括: get, post, put, delete, head, trace, connect, options
  2. path (也稱為 route 模式) 確定 Route 應該監聽哪些 URI(s) 併為它們提供響應。
  3. callback 是一個在給定 verb 和 path 上調用以生成並返回對相應 HTTP 請求的響應的 handler 函數。Callback 函數接收 request 對象和 response 對象作為參數。

這裏我們展示了使用 get verb 的基本結構:

get("/your-route-path/", (request, response) -> {
    // your callback code
});

3.2. Hello World API

讓我們創建一個簡單的 Web 服務,它包含兩個 GET 請求的 route,並返回“Hello”消息作為響應。這些 route 使用 get 方法,該方法是 class spark.Spark 的靜態導入:

import static spark.Spark.*;

public class HelloWorldService {
    public static void main(String[] args) {
 
        get("/hello", (req, res)->"Hello, world");
        
        get("/hello/:name", (req,res)->{
            return "Hello, "+ req.params(":name");
        });
    }
}

get 方法的第一個參數是 route 的路徑。第一個 route 包含一個靜態路徑,僅表示一個 URI (“/hello”).

第二個 route 的路徑 (“/hello/:name”) 包含 “name” 參數的佔位符,通過在參數前添加冒號 (“:”) 表示。此 route 將在對 URI 諸如 “/hello/Joe”“/hello/Mary” 這樣的請求進行 GET 請求時調用。

get 方法的第二個參數是一個 lambda 表達式,為這個框架增添了函數式編程的色彩。

lambda 表達式具有 request 和 response 作為參數,並幫助返回響應。我們將 controller 邏輯放在 lambda 表達式中,用於 REST API route,正如我們在本教程稍後看到的。

3.3. Testing the Hello World API

運行 class HelloWorldService 作為正常的 Java 類後,您可以使用定義的 route 上默認端口 4567 訪問服務。

讓我們查看第一個 route 的請求和響應:

Request:

GET http://localhost:4567/hello

Response:

Hello, world

讓我們測試第二個 route,在 route 路徑中傳遞 name 參數:

Request:

GET http://localhost:4567/hello/baeldung

Response:

Hello, baeldung

請看文本 “baeldung” 的放置在 URI 中用於匹配 route 模式 “/hello/:name” – 導致第二個 route 的 callback handler 函數被調用。

4. 設計一個 RESTful 服務在本節中,我們將為以下 用户 實體設計一個簡單的 REST Web 服務:

public class User {
    private String id;
    private String firstName;
    private String lastName;
    private String email;

    // constructors, getters and setters
}

4.1. 路由以下是構成我們的 API 的路由列表:

GET /users — 獲取所有用户列表
  • GET /users/:id — 獲取指定 ID 的用户
  • POST /users/:id — 添加用户
  • PUT /users/:id — 編輯特定用户
  • OPTIONS /users/:id — 檢查是否存在指定 ID 的用户
  • DELETE /users/:id — 刪除特定用户
  • 4.2. 用户服務以下是 UserService 接口,聲明瞭對 用户 實體進行 CRUD 操作:

    public interface UserService {
     
        public void addUser (User user);
        
        public Collection<User> getUsers ();
        public User getUser (String id);
        
        public User editUser (User user) 
          throws UserException;
        
        public void deleteUser (String id);
        
        public boolean userExist (String id);
    }

    為了演示目的,我們提供了一個 Map 實現的 UserService 接口在 GitHub 代碼中的實現,以模擬持久性。 您可以提供您自己的實現,其中包含數據庫和持久層

    4.3. JSON 響應結構以下是我們在 REST 服務中使用的響應 JSON 結構:

    {
        status: <STATUS>
        message: <TEXT-MESSAGE>
        data: <JSON-OBJECT>
    }

    status 字段的值可以是 SUCCESSERRORdata 字段將包含返回數據的 JSON 表示形式,例如 UserUsers 集合。

    當沒有返回數據,或者當 statusERROR 時,我們將填充 message 字段以傳達錯誤或缺少返回數據的原因。

    讓我們使用 Java 類來表示上述 JSON 結構:

    public class StandardResponse {
     
        private StatusResponse status;
        private String message;
        private JsonElement data;
        
        public StandardResponse(StatusResponse status) {
            // ...
        }
        public StandardResponse(StatusResponse status, String message) {
            // ...
        }
        public StandardResponse(StatusResponse status, JsonElement data) {
            // ...
        }
        
        // getters and setters
    }

    其中 StatusResponse 是以下枚舉定義的 enum

    public enum StatusResponse {
        SUCCESS ("Success"),
        ERROR ("Error");
     
        private String status;       
        // constructors, getters
    }

    5. Implementing RESTful Services

    Now let’s implement the routes and handlers for our REST API.

    5.1. Creating Controllers

    The following Java class contains the routes for our API, including the verbs and paths and an outline of the handlers for each route:

    public class SparkRestExample {
        public static void main(String[] args) {
            post("/users", (request, response) -> {
                //...
            });
            get("/users", (request, response) -> {
                //...
            });
            get("/users/:id", (request, response) -> {
                //...
            });
            put("/users/:id", (request, response) -> {
                //...
            });
            delete("/users/:id", (request, response) -> {
                //...
            });
            options("/users/:id", (request, response) -> {
                //...
            });
        }
    }
    

    We will show the full implementation of each route handler in the following subsections.

    5.2. Add User

    Below is the post method response handler which will add a User:

    post("/users", (request, response) -> {
        response.type("application/json");
        User user = new Gson().fromJson(request.body(), User.class);
        userService.addUser(user);
    
        return new Gson()
          .toJson(new StandardResponse(StatusResponse.SUCCESS));
    });
    

    Note: In this example, the JSON representation of the User object is passed as the raw body of a POST request.

    Let’s test the route:

    Request:

    POST http://localhost:4567/users
    {
        "id": "1012", 
        "email": "[email protected]", 
        "firstName": "Mac",
        "lastName": "Mason1"
    }
    

    Response:

    {
        "status":"SUCCESS"
    }
    

    5.3. Get All Users

    Below is the get method response handler which returns all users from the UserService:

    get("/users", (request, response) -> {
        response.type("application/json");
        return new Gson().toJson(
          new StandardResponse(StatusResponse.SUCCESS,new Gson()
            .toJsonTree(userService.getUsers())));
    });
    

    Now let’s test the route:

    Request:

    GET http://localhost:4567/users
    

    Response:

    {
        "status":"SUCCESS",
        "data":[
            {
                "id":"1014",
                "firstName":"John",
                "lastName":"Miller",
                "email":"[email protected]"
            },
            {
                "id":"1012",
                "firstName":"Mac",
                "lastName":"Mason1",
                "email":"[email protected]"
            }
        ]
    }
    

    5.4. Get User by Id

    Below is the get method response handler which returns a User with the given id:

    get("/users/:id", (request, response) -> {
        response.type("application/json");
        return new Gson().toJson(
          new StandardResponse(StatusResponse.SUCCESS,new Gson()
            .toJsonTree(userService.getUser(request.params(":id")))));
    });
    

    Now let’s test the route:

    Request:

    GET http://localhost:4567/users/1012
    

    Response:

    {
        "status":"SUCCESS",
        "data":{
            "id":"1012",
            "firstName":"Mac",
            "lastName":"Mason1",
            "email":"[email protected]"
        }
    }
    

    5.5. Edit a User

    Below is the put method response handler, which edits the user having the id supplied in the route pattern:

    put("/users/:id", (request, response) -> {
        response.type("application/json");
        User toEdit = new Gson().fromJson(request.body(), User.class);
        User editedUser = userService.editUser(toEdit);
                
        if (editedUser != null) {
            return new Gson().toJson(
              new StandardResponse(StatusResponse.SUCCESS,new Gson()
                .toJsonTree(editedUser)));
        } else {
            return new Gson().toJson(
              new StandardResponse(StatusResponse.ERROR,new Gson()
                .toJson("User not found or error in edit")));
        }
    });
    

    Note: In this example, the data are passed in the raw body of a POST request as a JSON object whose property names match the fields of the User object to be edited.

    Let’s test the route:

    Request:

    PUT http://localhost:4567/users/1012
    {
        "lastName": "Mason"
    }
    

    Response:

    {
        "status":"SUCCESS",
        "data":{
            "id":"1012",
            "firstName":"Mac",
            "lastName":"Mason",
            "email":"[email protected]"
        }
    }
    

    5.6. Delete a User

    Below is the delete method response handler, which will delete the User with the given id:

    delete("/users/:id", (request, response) -> {
        response.type("application/json");
        userService.deleteUser(request.params(":id"));
        return new Gson().toJson(
          new StandardResponse(StatusResponse.SUCCESS, "user deleted"));
    });
    

    Now, let’s test the route:

    Request:

    DELETE http://localhost:4567/users/1012
    

    Response:

    {
        "status":"SUCCESS",
        "message":"user deleted"
    }
    

    5.7. Check if User Exists

    The options method is a good choice for conditional checking. Below is the options method response handler which will check whether a User with the given id exists:

    options("/users/:id", (request, response) -> {
        response.type("application/json");
        return new Gson().toJson(
          new StandardResponse(StatusResponse.SUCCESS, 
            (userService.userExist(
              request.params(":id"))) ? "User exists" : "User does not exists" ));
    });
    

    Now let’s test the route:

    Request:

    OPTIONS http://localhost:4567/users/1012
    

    Response:

    {
        "status":"SUCCESS",
        "message":"User exists"
    }
    

    6. 結論

    在本文中,我們對 Spark 框架進行了快速介紹,用於快速 Web 開發。

    該框架主要用於在 Java 中生成微服務。 擁有 Java 知識的 Node.js 開發者,如果希望利用 JVM 庫構建的庫,將覺得這個框架非常適合。

    user avatar
    0 位用戶收藏了這個故事!
    收藏

    發佈 評論

    Some HTML is okay.