1. 简介
Spring Data REST 能帮我们省掉大量 REST 服务中重复性的模板代码。
本文将带你了解如何 对 Spring Data REST 默认的 HTTP 接口行为进行定制化配置。
2. Spring Data REST Repository 基础知识
首先,我们创建一个空接口并继承 CrudRepository,指定实体类型和主键类型:
public interface UserRepository extends CrudRepository<WebsiteUser, Long> {}
默认情况下,✅ Spring 会自动生成所有必要的映射路径,并为每个资源绑定合适的 HTTP 方法,返回正确的状态码。
如果不需要 CrudRepository 提供的所有方法,可以继承更基础的 Repository 接口,并 只暴露我们需要的方法:
public interface UserRepository extends Repository<WebsiteUser, Long> {
void deleteById(Long aLong);
}
当收到请求时,Spring 会根据 HTTP 方法和资源类型来调用接口中对应的方法(如果存在),否则返回 HTTP 状态码 ❌ 405 Method Not Allowed
。
比如上面的例子中,收到 DELETE 请求时,就会执行我们定义的 deleteById 方法。
3. 限制暴露的 HTTP 方法
假设我们有一个用户管理系统,对应的 UserRepository 继承了 CrudRepository:
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends CrudRepository<WebsiteUser, Long> {}
此时,所有的 CRUD 操作都被暴露出来。例如执行如下命令:
curl -v -X DELETE http://localhost:8080/users/<existing_user_id>
会返回 ✅ HTTP 状态码 204 No Content
,表示删除成功。
但如果现在我们希望 ❌ 对外隐藏 delete 操作,而内部仍然可以使用该方法,该怎么办?
我们可以在接口中显式声明 deleteById 方法,并加上注解 *@RestResource(exported = false)*,告诉 Spring Data REST 不要对外暴露这个方法:
@Override
@RestResource(exported = false)
void deleteById(Long aLong);
再次执行同样的 DELETE 请求,就会收到 ❌ 405 Method Not Allowed
的响应。
4. 自定义支持的 HTTP 方法
@RestResource 注解不仅可以控制方法是否暴露,还可以用来 自定义 URL 路径和 HATEOAS 返回的链接 ID。
它的两个常用参数是:
- path:用于设置 URL 路径
- rel:用于设置 JSON 中的 link ID
继续以 UserRepository 为例,我们添加一个 findByEmail 查询方法:
WebsiteUser findByEmail(@Param("email") String email);
访问 http://localhost:8080/users/search/
可以看到新方法出现在返回结果中:
{
"_links": {
"findByEmail": {
"href": "http://localhost:8080/users/search/findByEmail{?email}"
},
"self": {
"href": "http://localhost:8080/users/search/"
}
}
}
如果你不喜欢默认生成的路径名,可以直接通过 @RestResource 来修改,而无需更改方法名:
@RestResource(path = "byEmail", rel = "customFindMethod")
WebsiteUser findByEmail(@Param("email") String email);
重新访问后,返回的 JSON 就会变成:
{
"_links": {
"customFindMethod": {
"href": "http://localhost:8080/users/search/byEmail{?email}",
"templated": true
},
"self": {
"href": "http://localhost:8080/users/search/"
}
}
}
5. 编程式配置
有时我们需要更精细地控制哪些 HTTP 方法可以被暴露。比如,集合资源上的 POST、单个资源上的 PUT 和 PATCH 都会调用同一个 save 方法。
✅ 从 Spring Data REST 3.1 开始(对应 Spring Boot 2.1),我们可以通过 ExposureConfiguration 类来 针对特定 HTTP 方法进行暴露控制。
它提供了一个基于 Lambda 的 API,可以定义全局规则或按类型分别控制。
举个例子,我们可以禁止对 WebsiteUser 类型的资源执行 PATCH 请求:
public class RestConfig implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration restConfig,
CorsRegistry cors) {
ExposureConfiguration config = restConfig.getExposureConfiguration();
config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) ->
httpMethods.disable(HttpMethod.PATCH));
}
}
⚠️ 注意:这种配置方式更适合需要统一控制多个资源的场景,简单粗暴但灵活。
6. 总结
这篇文章介绍了如何在 Spring Data REST 中定制默认的 HTTP 接口行为,包括:
- 控制方法是否暴露
- 自定义 URL 路径与 link ID
- 使用编程方式进行细粒度配置
如需查看完整示例代码,请前往我们的 GitHub 项目。