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 依赖项:
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.5.4</version>
</dependency>
您可以在Maven Central上找到最新版本的 Spark 。
2.2. 格森图书馆
在示例中的各个地方,我们将使用 Gson 库进行 JSON 操作。要在您的项目中包含 Gson,请在您的pom.xml中包含此依赖项:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
您可以在Maven Central上找到最新版本的 Gson 。
3. Spark 框架入门
让我们看一下 Spark 应用程序的基本构建块,并演示一个快速 Web 服务。
3.1。路线
Spark Java 中的 Web 服务建立在路由及其处理程序之上。路由是 Spark 中必不可少的元素。根据文档,每条路由都由三个简单的部分组成——动词、路径和回调。
- 动词是对应于 HTTP 方法的方法。动词方法包括:get、post、put、delete、head、trace、connect和options
- 路径(也称为路由模式)确定路由应该监听哪些 URI 并提供响应
- 回调是一个处理函数,为给定的动词和路径调用,以便生成并返回对相应 HTTP 请求的响应。回调将请求对象和响应对象作为参数
在这里,我们展示了使用get动词的路由的基本结构:
get("/your-route-path/", (request, response) -> {
// your callback code
});
3.2. 你好世界API
让我们创建一个简单的 Web 服务,它有两条 GET 请求路由并返回“Hello”消息作为响应。这些路由使用get方法,这是从类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方法的第一个参数是路由的路径。第一个路由包含一个静态路径,仅代表一个 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 服务:
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 — 编辑特定用户
- 选项 /users/:id — 检查是否存在具有给定 id 的用户
- DELETE /users/:id — 删除特定用户
4.2. 用户服务
下面是为User实体声明 CRUD 操作的UserService接口:
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);
}
出于演示目的,我们在 GitHub 代码中提供了这个UserService接口的Map实现来模拟持久性。您可以使用您选择的数据库和持久层来提供您自己的实现。
4.3. JSON 响应结构
下面是我们的 REST 服务中使用的响应的 JSON 结构:
{
status: <STATUS>
message: <TEXT-MESSAGE>
data: <JSON-OBJECT>
}
状态字段值可以是SUCCESS或ERROR。data字段将包含返回数据的 JSON 表示,例如User或Users集合。
当没有返回数据,或者状态为ERROR时,我们将填充消息字段以传达错误或缺少返回数据的原因。
让我们用一个 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是一个枚举,定义如下:
public enum StatusResponse {
SUCCESS ("Success"),
ERROR ("Error");
private String status;
// constructors, getters
}
5. 实现 RESTful 服务
现在让我们为我们的 REST API 实现路由和处理程序。
5.1。创建控制器
以下 Java 类包含我们 API 的路由,包括动词和路径以及每个路由的处理程序大纲:
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) -> {
//...
});
}
}
我们将在以下小节中展示每个路由处理程序的完整实现。
5.2. 添加用户
下面是post方法响应处理程序,它将添加一个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));
});
注意:在此示例中,用户对象的 JSON 表示作为 POST 请求的原始正文传递。
让我们测试一下路线:
要求:
POST http://localhost:4567/users
{
"id": "1012",
"email": "your-email@your-domain.com",
"firstName": "Mac",
"lastName": "Mason1"
}
回复:
{
"status":"SUCCESS"
}
5.3. 获取所有用户
下面是从UserService返回所有用户的get方法响应处理程序:
get("/users", (request, response) -> {
response.type("application/json");
return new Gson().toJson(
new StandardResponse(StatusResponse.SUCCESS,new Gson()
.toJsonTree(userService.getUsers())));
});
现在让我们测试一下路线:
要求:
GET http://localhost:4567/users
回复:
{
"status":"SUCCESS",
"data":[
{
"id":"1014",
"firstName":"John",
"lastName":"Miller",
"email":"your-email@your-domain.com"
},
{
"id":"1012",
"firstName":"Mac",
"lastName":"Mason1",
"email":"your-email@your-domain.com"
}
]
}
5.4. 按 ID 获取用户
下面是get方法响应处理程序,它返回具有给定id的User:
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")))));
});
现在让我们测试一下路线:
要求:
GET http://localhost:4567/users/1012
回复:
{
"status":"SUCCESS",
"data":{
"id":"1012",
"firstName":"Mac",
"lastName":"Mason1",
"email":"your-email@your-domain.com"
}
}
5.5. 编辑用户
下面是put方法响应处理程序,它编辑具有路由模式中提供的id的用户:
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")));
}
});
注意:在此示例中,数据作为 JSON 对象在 POST 请求的原始正文中传递,其属性名称与要编辑的用户对象的字段匹配。
让我们测试一下路线:
要求:
PUT http://localhost:4567/users/1012
{
"lastName": "Mason"
}
回复:
{
"status":"SUCCESS",
"data":{
"id":"1012",
"firstName":"Mac",
"lastName":"Mason",
"email":"your-email@your-domain.com"
}
}
5.6. 删除用户
下面是删除方法响应处理程序,它将删除具有给定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"));
});
现在,让我们测试一下路线:
要求:
DELETE http://localhost:4567/users/1012
回复:
{
"status":"SUCCESS",
"message":"user deleted"
}
5.7. 检查用户是否存在
options方法是条件检查的不错选择。下面是options方法响应处理程序,它将检查具有给定id的用户是否存在:
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" ));
});
现在让我们测试一下路线:
要求:
OPTIONS http://localhost:4567/users/1012
回复:
{
"status":"SUCCESS",
"message":"User exists"
}
6.结论
在本文中,我们快速介绍了用于快速 Web 开发的 Spark 框架。
该框架主要用于在 Java 中生成微服务。具有 Java 知识且想要利用基于 JVM 库构建的库的Node.js开发人员应该对使用此框架感到宾至如归。
和往常一样,您可以在Github 项目中找到本教程的所有资源。