• 使用 Spark Java 框架构建 API


    1.简介

    在本文中,我们将快速介绍Spark 框架。Spark 框架是一个快速开发的 Web 框架,其灵感来自 Ruby 的 Sinatra 框架,并围绕 Java 8 Lambda 表达式理念构建,使其比使用其他 Java 框架编写的大多数应用程序更简洁。

    如果您想在使用 Java 开发 Web API 或微服务时获得类似Node.js的体验,这是一个不错的选择。使用 Spark,您只需不到 10 行代码就可以准备好提供 JSON 的 REST API。

    我们将从一个“Hello World”示例快速开始,然后是一个简单的 REST API。

    2.Maven依赖

    2.1。星火框架

    在pom.xml中包含以下 Maven 依赖项:

    1. <dependency>
    2. <groupId>com.sparkjavagroupId>
    3. <artifactId>spark-coreartifactId>
    4. <version>2.5.4version>
    5. dependency>

    您可以在Maven Central上找到最新版本的 Spark 。

    2.2. 格森图书馆

    在示例中的各个地方,我们将使用 Gson 库进行 JSON 操作。要在您的项目中包含 Gson,请在您的pom.xml中包含此依赖项:

    1. <dependency>
    2. <groupId>com.google.code.gsongroupId>
    3. <artifactId>gsonartifactId>
    4. <version>2.8.0version>
    5. dependency>

    您可以在Maven Central上找到最新版本的 Gson 。

    3. Spark 框架入门

    让我们看一下 Spark 应用程序的基本构建块,并演示一个快速 Web 服务。

    3.1。路线

    Spark Java 中的 Web 服务建立在路由及其处理程序之上。路由是 Spark 中必不可少的元素。根据文档,每条路由都由三个简单的部分组成——动词路径回调

    1. 动词是对应于 HTTP 方法的方法。动词方法包括:get、post、put、delete、head、trace、connectoptions
    2. 路径(也称为路由模式)确定路由应该监听哪些 URI 并提供响应
    3. 回调是一个处理函数,为给定的动词和路径调用,以便生成并返回对相应 HTTP 请求的响应。回调将请求对象和响应对象作为参数

    在这里,我们展示了使用get动词的路由的基本结构:

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

    3.2. 你好世界API

    让我们创建一个简单的 Web 服务,它有两条 GET 请求路由并返回“Hello”消息作为响应。这些路由使用get方法,这是从类spark.Spark的静态导入:

    1. import static spark.Spark.*;
    2. public class HelloWorldService {
    3. public static void main(String[] args) {
    4. get("/hello", (req, res)->"Hello, world");
    5. get("/hello/:name", (req,res)->{
    6. return "Hello, "+ req.params(":name");
    7. });
    8. }
    9. }

    get方法的第一个参数是路由的路径。第一个路由包含一个静态路径,仅代表一个 URI(“/hello”)。

    第二条路由的路径(“/hello/:name” )包含“name”参数的占位符,通过在参数前面加上冒号(“:”)来表示。将调用此路由以响应对 URI 的 GET 请求,例如“/hello/Joe”“/hello/Mary”

    get方法的第二个参数是一个lambda 表达式,为该框架提供了函数式编程风格。

    lambda 表达式将请求和响应作为参数并帮助返回响应。我们将把控制器逻辑放在 REST API 路由的 lambda 表达式中,我们将在本教程后面看到。

    3.3. 测试 Hello World API

    将HelloWorldService类作为普通 Java 类运行后,您将能够使用上述get方法定义的路由在其默认端口4567上访问该服务。

    让我们看看第一个路由的请求和响应:

    要求:

    GET http://localhost:4567/hello

    回复:

    Hello, world

    让我们测试第二条路由,在其路径中传递name参数:

    要求:

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

    回复:

    Hello, baeldung

    了解如何使用 URI 中文本“baeldung”的位置来匹配路由模式“/hello/:name” ——导致调用第二个路由的回调处理函数。

    4. 设计一个 RESTful 服务

    在本节中,我们将为以下用户实体设计一个简单的 REST Web 服务:

    1. public class User {
    2. private String id;
    3. private String firstName;
    4. private String lastName;
    5. private String email;
    6. // constructors, getters and setters
    7. }

    4.1。路线

    让我们列出构成我们 API 的路由:

    • GET /users — 获取所有用户的列表
    • GET /users/:id — 获取给定 id 的用户
    • POST /users/:id — 添加用户
    • PUT /users/:id — 编辑特定用户
    • 选项 /users/:id — 检查是否存在具有给定 id 的用户
    • DELETE /users/:id — 删除特定用户

    4.2. 用户服务

    下面是为User实体声明 CRUD 操作的UserService接口:

    1. public interface UserService {
    2. public void addUser (User user);
    3. public Collection getUsers ();
    4. public User getUser (String id);
    5. public User editUser (User user)
    6. throws UserException;
    7. public void deleteUser (String id);
    8. public boolean userExist (String id);
    9. }

    出于演示目的,我们在 GitHub 代码中提供了这个UserService接口的Map实现来模拟持久性。您可以使用您选择的数据库和持久层来提供您自己的实现。

    4.3. JSON 响应结构

    下面是我们的 REST 服务中使用的响应的 JSON 结构:

    1. {
    2. status: <STATUS>
    3. message: <TEXT-MESSAGE>
    4. data: <JSON-OBJECT>
    5. }

    状态字段值可以是SUCCESSERRORdata字段将包含返回数据的 JSON 表示,例如User或Users集合。

    当没有返回数据,或者状态ERROR时,我们将填充消息字段以传达错误或缺少返回数据的原因。

    让我们用一个 Java 类来表示上面的 JSON 结构:

    1. public class StandardResponse {
    2. private StatusResponse status;
    3. private String message;
    4. private JsonElement data;
    5. public StandardResponse(StatusResponse status) {
    6. // ...
    7. }
    8. public StandardResponse(StatusResponse status, String message) {
    9. // ...
    10. }
    11. public StandardResponse(StatusResponse status, JsonElement data) {
    12. // ...
    13. }
    14. // getters and setters
    15. }

    其中StatusResponse是一个枚举,定义如下:

    1. public enum StatusResponse {
    2. SUCCESS ("Success"),
    3. ERROR ("Error");
    4. private String status;
    5. // constructors, getters
    6. }

    5. 实现 RESTful 服务

    现在让我们为我们的 REST API 实现路由和处理程序。

    5.1。创建控制器

    以下 Java 类包含我们 API 的路由,包括动词和路径以及每个路由的处理程序大纲:

    1. public class SparkRestExample {
    2. public static void main(String[] args) {
    3. post("/users", (request, response) -> {
    4. //...
    5. });
    6. get("/users", (request, response) -> {
    7. //...
    8. });
    9. get("/users/:id", (request, response) -> {
    10. //...
    11. });
    12. put("/users/:id", (request, response) -> {
    13. //...
    14. });
    15. delete("/users/:id", (request, response) -> {
    16. //...
    17. });
    18. options("/users/:id", (request, response) -> {
    19. //...
    20. });
    21. }
    22. }

    我们将在以下小节中展示每个路由处理程序的完整实现。

    5.2. 添加用户

    下面是post方法响应处理程序,它将添加一个User

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

    注意:在此示例中,用户对象的 JSON 表示作为 POST 请求的原始正文传递。

    让我们测试一下路线:

    要求:

    1. POST http://localhost:4567/users
    2. {
    3. "id": "1012",
    4. "email": "your-email@your-domain.com",
    5. "firstName": "Mac",
    6. "lastName": "Mason1"
    7. }

    回复:

    1. {
    2. "status":"SUCCESS"
    3. }

    5.3. 获取所有用户

    下面是从UserService返回所有用户的get方法响应处理程序:

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

    现在让我们测试一下路线:

    要求:

    GET http://localhost:4567/users

    回复:

    1. {
    2. "status":"SUCCESS",
    3. "data":[
    4. {
    5. "id":"1014",
    6. "firstName":"John",
    7. "lastName":"Miller",
    8. "email":"your-email@your-domain.com"
    9. },
    10. {
    11. "id":"1012",
    12. "firstName":"Mac",
    13. "lastName":"Mason1",
    14. "email":"your-email@your-domain.com"
    15. }
    16. ]
    17. }

    5.4. 按 ID 获取用户

    下面是get方法响应处理程序,它返回具有给定id的User

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

    现在让我们测试一下路线:

    要求:

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

    回复:

    1. {
    2. "status":"SUCCESS",
    3. "data":{
    4. "id":"1012",
    5. "firstName":"Mac",
    6. "lastName":"Mason1",
    7. "email":"your-email@your-domain.com"
    8. }
    9. }

    5.5. 编辑用户

    下面是put方法响应处理程序,它编辑具有路由模式中提供的id的用户:

    1. put("/users/:id", (request, response) -> {
    2. response.type("application/json");
    3. User toEdit = new Gson().fromJson(request.body(), User.class);
    4. User editedUser = userService.editUser(toEdit);
    5. if (editedUser != null) {
    6. return new Gson().toJson(
    7. new StandardResponse(StatusResponse.SUCCESS,new Gson()
    8. .toJsonTree(editedUser)));
    9. } else {
    10. return new Gson().toJson(
    11. new StandardResponse(StatusResponse.ERROR,new Gson()
    12. .toJson("User not found or error in edit")));
    13. }
    14. });

    注意:在此示例中,数据作为 JSON 对象在 POST 请求的原始正文中传递,其属性名称与要编辑的用户对象的字段匹配。

    让我们测试一下路线:

    要求:

    1. PUT http://localhost:4567/users/1012
    2. {
    3. "lastName": "Mason"
    4. }

    回复:

    1. {
    2. "status":"SUCCESS",
    3. "data":{
    4. "id":"1012",
    5. "firstName":"Mac",
    6. "lastName":"Mason",
    7. "email":"your-email@your-domain.com"
    8. }
    9. }

    5.6. 删除用户

    下面是删除方法响应处理程序,它将删除具有给定id的用户

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

    现在,让我们测试一下路线:

    要求:

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

    回复:

    1. {
    2. "status":"SUCCESS",
    3. "message":"user deleted"
    4. }

    5.7. 检查用户是否存在

    options方法是条件检查的不错选择。下面是options方法响应处理程序,它将检查具有给定id的用户是否存在:

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

    现在让我们测试一下路线:

    要求:

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

    回复:

    1. {
    2. "status":"SUCCESS",
    3. "message":"User exists"
    4. }

    6.结论

    在本文中,我们快速介绍了用于快速 Web 开发的 Spark 框架。

    该框架主要用于在 Java 中生成微服务。具有 Java 知识且想要利用基于 JVM 库构建的库的Node.js开发人员应该对使用此框架感到宾至如归。

    和往常一样,您可以在Github 项目中找到本教程的所有资源。

  • 相关阅读:
    vue 项目全局<meta>添加自定义内容
    stm32之27.iic协议oled显示
    如何让您的公司内容满足 GDPR 合规性
    Linux-VI和VIM
    1015. 可被 K 整除的最小整数
    WeakHashMap 和 HashMap 的区别是什么,何时使用?
    在eclipse中安装properties插件PropertiesEditor及设置(附图),ASCII码转换成中文
    代码随想录算法训练营第六十天| LeetCode84.柱状图中最大的矩形
    使用Feign远程调用快速入门
    GET请求
  • 原文地址:https://blog.csdn.net/allway2/article/details/126687387