跳到主要内容

配置 REST URL 路径

DeepSeek V3 中英对照 Configuring the REST URL Path

你可以配置 JPA 仓库资源导出的 URL 路径段。为此,在类级别或查询方法级别添加注解即可。

默认情况下,导出器会使用领域类的名称来公开你的 CrudRepository。Spring Data REST 还会应用 Evo Inflector 来对这个词进行复数化处理。考虑以下仓库定义:

interface PersonRepository extends CrudRepository<Person, Long> {}
java

前面示例中定义的仓库暴露在 [localhost:8080/persons/](http://localhost:8080/persons/)

要更改存储库的导出方式,可以在类级别添加 @RestResource 注解,如下例所示:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {}
java

在前面示例中定义的仓库可以通过 [localhost:8080/people/](http://localhost:8080/people/) 访问。

如果你定义了查询方法,这些方法也会默认通过它们的名称暴露出来,如下例所示:

interface PersonRepository extends CrudRepository<Person, Long> {

List<Person> findByName(String name);
}
java

在前面的示例中,该方法暴露在 [localhost:8080/persons/search/findByName](http://localhost:8080/persons/search/findByName)

备注

所有的查询方法资源都暴露在 search 资源下。

要更改此查询方法暴露在 URL 下的路径段,你可以再次使用 @RestResource 注解,如下例所示:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

@RestResource(path = "names")
List<Person> findByName(String name);
}
java

现在,前面示例中的查询方法已经暴露在 [localhost:8080/people/search/names](http://localhost:8080/people/search/names) 上。

处理 rel 属性

由于这些资源都是可发现的,您还可以影响 rel 属性在导出器发送的链接中的显示方式。

例如,在默认配置下,如果您向 [localhost:8080/persons/search](http://localhost:8080/persons/search) 发出请求以了解暴露了哪些查询方法,您将收到类似于以下的链接列表:

{
"_links" : {
"findByName" : {
"href" : "http://localhost:8080/persons/search/findByName"
}
}
}
javascript

要更改 rel 值,请在 @RestResource 注解上使用 rel 属性,如下例所示:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

@RestResource(path = "names", rel = "names")
List<Person> findByName(String name);
}
java

前面的示例将生成以下链接值:

{
"_links" : {
"names" : {
"href" : "http://localhost:8080/persons/search/names"
}
}
}
javascript
备注

这些 JSON 片段假设您使用 Spring Data REST 的默认格式 HAL。您可以关闭 HAL,这将导致输出看起来不同。然而,您覆盖 rel 名称的能力完全独立于渲染格式。

你可以更改存储库的 rel,如下例所示:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

@RestResource(path = "names", rel = "names")
List<Person> findByName(String name);
}
java

修改仓库的 rel 属性会改变顶层的名称,如下例输出所示:

{
"_links" : {
"people" : {
"href" : "http://localhost:8080/people"
},

}
}
javascript

在前面展示的输出中的顶层片段:

  • path = "people"href 的值从 /persons 更改为 /people

  • rel = "people" 将该链接的名称从 persons 更改为 people

当你导航到该仓库的 search 资源时,finder 方法的 @RestResource 注解已更改了路径,如下所示:

{
"_links" : {
"names" : {
"href" : "http://localhost:8080/people/search/names"
}
}
}
javascript

在您的仓库定义中,这组注解导致了以下更改:

  • 仓库级别注解的 path = "people" 体现在基础 URI 中,即 /people

  • 包含查找方法会为你提供 /people/search

  • path = "names" 会创建一个 URI,即 /people/search/names

  • rel = "names" 将该链接的名称从 findByNames 更改为 names

隐藏某些仓库、查询方法或字段

你可能不希望某个资源库、资源库上的查询方法或实体的某个字段被导出。例如,隐藏 User 对象上的 password 字段等敏感数据。为了告诉导出器不要导出这些项,可以使用 @RestResource 注解,并将 exported 设置为 false

例如,要跳过导出某个仓库,您可以创建一个类似于以下示例的仓库定义:

@RepositoryRestResource(exported = false)
interface PersonRepository extends CrudRepository<Person, Long> {}
java

要跳过导出查询方法,你可以使用 @RestResource(exported = false) 注解该查询方法,如下所示:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

@RestResource(exported = false)
List<Person> findByName(String name);
}
java

同样地,要跳过导出一个字段,你可以使用 @RestResource(exported = false) 注解该字段,如下所示:

@Entity
public class Person {

@Id @GeneratedValue private Long id;

@OneToMany
@RestResource(exported = false)
private Map<String, Profile> profiles;
}
java
注意

投影提供了一种改变导出内容的方式,从而有效地绕过这些设置。如果你为同一个领域对象创建了任何投影,请确保不要导出这些字段。

隐藏仓库的 CRUD 方法

如果你不想在 CrudRepository 上暴露保存或删除方法,你可以通过覆盖你想要关闭的方法并在覆盖的版本上添加 @RestResource(exported = false) 设置来实现。例如,为了防止 HTTP 用户调用 CrudRepository 的删除方法,覆盖所有这些方法并在覆盖的方法上添加注解,如下所示:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

@Override
@RestResource(exported = false)
void delete(Long id);

@Override
@RestResource(exported = false)
void delete(Person entity);
}
java
注意

重要的是你需要同时重写 两个 delete 方法。为了追求更快的运行时性能,导出器目前使用了一种较为简单的算法来确定使用哪个 CRUD 方法。目前,你不能关闭接受 ID 的 delete 方法,而导出接受实体实例的版本。目前,你只能选择导出或不导出 delete 方法。如果你想关闭它们,请记住你需要将两个版本都标注为 exported = false