配置 REST URL 路径
你可以配置 JPA 仓库资源导出的 URL 路径段。为此,在类级别或查询方法级别添加注解即可。
默认情况下,导出器会使用领域类的名称来公开你的 CrudRepository
。Spring Data REST 还会应用 Evo Inflector 来对这个词进行复数化处理。考虑以下仓库定义:
interface PersonRepository extends CrudRepository<Person, Long> {}
前面示例中定义的仓库暴露在 [localhost:8080/persons/](http://localhost:8080/persons/)
。
要更改存储库的导出方式,可以在类级别添加 @RestResource
注解,如下例所示:
@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {}
在前面示例中定义的仓库可以通过 [localhost:8080/people/](http://localhost:8080/people/)
访问。
如果你定义了查询方法,这些方法也会默认通过它们的名称暴露出来,如下例所示:
interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findByName(String name);
}
在前面的示例中,该方法暴露在 [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);
}
现在,前面示例中的查询方法已经暴露在 [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"
}
}
}
要更改 rel
值,请在 @RestResource
注解上使用 rel
属性,如下例所示:
@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {
@RestResource(path = "names", rel = "names")
List<Person> findByName(String name);
}
前面的示例将生成以下链接值:
{
"_links" : {
"names" : {
"href" : "http://localhost:8080/persons/search/names"
}
}
}
这些 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);
}
修改仓库的 rel
属性会改变顶层的名称,如下例输出所示:
{
"_links" : {
"people" : {
"href" : "http://localhost:8080/people"
},
…
}
}
在前面展示的输出中的顶层片段:
-
path = "people"
将href
的值从/persons
更改为/people
。 -
rel = "people"
将该链接的名称从persons
更改为people
。
当你导航到该仓库的 search
资源时,finder 方法的 @RestResource
注解已更改了路径,如下所示:
{
"_links" : {
"names" : {
"href" : "http://localhost:8080/people/search/names"
}
}
}
在您的仓库定义中,这组注解导致了以下更改:
-
仓库级别注解的
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> {}
要跳过导出查询方法,你可以使用 @RestResource(exported = false)
注解该查询方法,如下所示:
@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {
@RestResource(exported = false)
List<Person> findByName(String name);
}
同样地,要跳过导出一个字段,你可以使用 @RestResource(exported = false)
注解该字段,如下所示:
@Entity
public class Person {
@Id @GeneratedValue private Long id;
@OneToMany
@RestResource(exported = false)
private Map<String, Profile> profiles;
}
投影提供了一种改变导出内容的方式,从而有效地绕过这些设置。如果你为同一个领域对象创建了任何投影,请确保不要导出这些字段。
隐藏仓库的 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);
}
重要的是你需要同时重写 两个 delete
方法。为了追求更快的运行时性能,导出器目前使用了一种较为简单的算法来确定使用哪个 CRUD 方法。目前,你不能关闭接受 ID 的 delete
方法,而导出接受实体实例的版本。目前,你只能选择导出或不导出 delete
方法。如果你想关闭它们,请记住你需要将两个版本都标注为 exported = false
。