1. 概述
LinkRest 是一个开源框架,专门用于构建数据驱动的 REST Web 服务。它基于 JAX-RS 和 Apache Cayenne ORM 构建,采用 HTTP/JSON 消息协议。
简单来说,这个框架提供了一种简单粗暴的方式将数据存储暴露在 Web 上。接下来我们将通过实际案例,展示如何使用 LinkRest 快速构建 REST 服务访问数据模型。
2. Maven 依赖
要开始使用 LinkRest,首先需要添加核心依赖:
<dependency>
<groupId>com.nhl.link.rest</groupId>
<artifactId>link-rest</artifactId>
<version>2.9</version>
</dependency>
这个依赖会自动引入 cayenne-server。此外,我们选择 Jersey 作为 JAX-RS 实现,所以需要添加:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
为了方便演示,我们使用内存数据库 H2:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
3. Cayenne 数据模型
我们将使用包含 Department(部门)和 Employee(员工)两个实体的数据模型,它们是一对多关系:
⚠️ 注意:LinkRest 必须配合 Apache Cayenne ORM 生成的数据对象使用。本文不深入讲解 Cayenne,详情请参考官方文档。
我们将 Cayenne 项目配置保存在 cayenne-linkrest-project.xml
文件中。运行 cayenne-maven-plugin 后,会生成:
- 两个抽象类
_Department
和_Employee
(继承自 CayenneDataObject) - 两个具体类
Department
和Employee
这些具体类就是我们要在 LinkRest 中使用的类。
4. LinkRest 应用启动
要运行 REST 接口,需要先配置运行环境。由于我们使用 Jersey,创建一个扩展 ResourceConfig 的类:
@ApplicationPath("/linkrest")
public class LinkRestApplication extends ResourceConfig {
public LinkRestApplication() {
packages("com.baeldung.linkrest.apis");
// 加载 linkrest 运行时
}
}
在构造函数中初始化 LinkRestRuntime:
ServerRuntime cayenneRuntime = ServerRuntime.builder()
.addConfig("cayenne-linkrest-project.xml")
.build();
LinkRestRuntime lrRuntime = LinkRestBuilder.build(cayenneRuntime);
super.register(lrRuntime);
最后在 web.xml
中注册:
<servlet>
<servlet-name>linkrest</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.baeldung.LinkRestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>linkrest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5. REST 资源
现在可以开始编写 REST 资源了。REST 接口使用标准 JAX-RS 注解创建,响应通过 LinkRest 类构建。
我们将为 /department
路径编写 CRUD 接口。首先创建 DepartmentResource
类:
@Path("department")
@Produces(MediaType.APPLICATION_JSON)
public class DepartmentResource {
@Context
private Configuration config;
// ...
}
LinkRest 需要注入 JAX-RS 的 Configuration 实例。
5.1. 使用 POST 创建实体
LinkRest 的 create()
方法返回 UpdateBuilder
:
@POST
public SimpleResponse create(String data) {
return LinkRest.create(Department.class, config).sync(data);
}
data
参数可以是单个 Department 的 JSON 对象,也可以是对象数组。sync()
方法会创建对象并插入数据库,返回 SimpleResponse
。
✅ 支持的响应类型:
DataResponse<T>
- 表示 T 的集合MetadataResponse<T>
- 包含类型元数据SimpleResponse
- 包含 success 和 message 属性
用 curl 添加部门:
curl -i -X POST -H "Content-Type:application/json"
-d "{"name":"IT"}" http://localhost:8080/linkrest/department
返回状态码 201 Created 和响应体:
{"success":true}
批量创建:
curl -i -X POST -H "Content-Type:application/json"
-d "[{"name":"HR"},{"name":"Marketing"}]"
http://localhost:8080/linkrest/department
5.2. 使用 GET 读取实体
查询主要使用 select()
方法,返回 SelectBuilder
。获取所有部门:
@GET
public DataResponse<Department> getAll(@Context UriInfo uriInfo) {
return LinkRest.select(Department.class, config).uri(uriInfo).get();
}
uri()
设置请求信息,get()
返回 DataResponse<Department>
。用 curl 测试:
curl -i -X GET http://localhost:8080/linkrest/department
响应格式:
{"data":[
{"id":200,"name":"IT"},
{"id":201,"name":"Marketing"},
{"id":202,"name":"HR"}
],
"total":3}
查询单个对象使用 getOne()
:
@GET
@Path("{id}")
public DataResponse<Department> getOne(@PathParam("id") int id,
@Context UriInfo uriInfo) {
return LinkRest.select(Department.class, config)
.byId(id).uri(uriInfo).getOne();
}
测试:
curl -i -X GET http://localhost:8080/linkrest/department/200
响应:
{"data":[{"id":200,"name":"IT"}],"total":1}
5.3. 使用 PUT 更新实体
更新使用 update()
或 createOrUpdate()
(不存在则创建):
@PUT
public SimpleResponse createOrUpdate(String data) {
return LinkRest.createOrUpdate(Department.class, config).sync(data);
}
更新部门名称:
curl -i -X PUT -H "Content-Type:application/json"
-d "{"id":202,"name":"Human Resources"}"
http://localhost:8080/linkrest/department
验证更新:
curl -i -X GET http://localhost:8080/linkrest/department/202
结果:
{"data":[
{"id":202,"name":"Human Resources"}
],
"total":1}
5.4. 使用 DELETE 删除实体
删除使用 delete()
方法:
@DELETE
@Path("{id}")
public SimpleResponse delete(@PathParam("id") int id) {
return LinkRest.delete(Department.class, config).id(id).delete();
}
测试:
curl -i -X DELETE http://localhost:8080/linkrest/department/202
5.5. 处理实体关系
LinkRest 简化了关系操作。Department 和 Employee 是一对多关系,添加子资源:
@Path("{id}/employees")
public EmployeeSubResource getEmployees(
@PathParam("id") int id, @Context UriInfo uriInfo) {
return new EmployeeSubResource(id);
}
EmployeeSubResource
类:
@Produces(MediaType.APPLICATION_JSON)
public class EmployeeSubResource {
private Configuration config;
private int departmentId;
public EmployeeSubResource(int departmentId, Configuration configuration) {
this.departmentId = departmentId;
this.config = configuration;
}
public EmployeeSubResource() {
}
}
⚠️ 注意:必须有无参构造函数才能序列化为 JSON。
获取部门员工:
@GET
public DataResponse<Employee> getAll(@Context UriInfo uriInfo) {
return LinkRest.select(Employee.class, config)
.toManyParent(Department.class, departmentId, Department.EMPLOYEES)
.uri(uriInfo).get();
}
toManyParent()
方法按父实体过滤。添加员工:
curl -i -X POST -H "Content-Type:application/json"
-d "{"name":"John"}" http://localhost:8080/linkrest/department/200/employees
查看员工列表:
curl -i -X GET "http://localhost:8080/linkrest/department/200/employees
响应:
{"data":[{"id":200,"name":"John"}],"total":1}
6. 通过请求参数定制响应
LinkRest 支持通过请求参数定制响应,实现过滤、排序、分页和属性选择。
6.1. 过滤
使用 cayenneExp
参数过滤,遵循 Cayenne 表达式 语法:
curl -i -X GET http://localhost:8080/linkrest/department?cayenneExp=name='IT'
6.2. 排序
使用 sort
和 dir
参数:
curl -i -X GET "http://localhost:8080/linkrest/department?sort=name&dir=ASC"
6.3. 分页
使用 start
和 limit
参数:
curl -i -X GET "http://localhost:8080/linkrest/department?start=0&limit=2
6.4. 选择属性
使用 include
和 exclude
控制返回字段:
仅返回部门名称:
curl -i -X GET "http://localhost:8080/linkrest/department?include=name
返回名称和员工姓名:
curl -i -X GET "http://localhost:8080/linkrest/department?include=name&include=employees.name
7. 总结
本文展示了如何使用 LinkRest 框架快速构建 REST 接口暴露数据模型。核心优势包括:
- ✅ 基于 JAX-RS 和 Cayenne ORM
- ✅ 简化 CRUD 操作
- ✅ 支持关系处理
- ✅ 灵活的响应定制
完整示例代码请查看 GitHub 仓库。踩坑提示:确保 Cayenne 配置正确,否则运行时会报错。