配置 REST URL 路径

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

默认情况下,导出器使用域类的名称来公开您的 CrudRepository。Spring Data REST 还应用了 Evo Inflector 来将此词语复数化。考虑以下仓库定义

interface PersonRepository extends CrudRepository<Person, Long> {}

由上述示例定义的仓库在 localhost:8080/persons/ 中公开。

要更改仓库的导出方式,请在类级别添加 @RestResource 注解,如下例所示

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

前面示例中定义的资源库可以通过 localhost:8080/people/ 访问。

如果您定义了查询方法,这些方法也会默认以其名称公开,如下面的示例所示

interface PersonRepository extends CrudRepository<Person, Long> {

  List<Person> findByName(String name);
}

前面示例中的方法在 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 公开。

处理 rel 属性

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

例如,在默认配置中,如果您向 localhost:8080/persons/search 发出请求以找出公开的查询方法,您将收到类似于以下内容的链接列表

{
  "_links" : {
    "findByName" : {
      "href" : "https://127.0.0.1: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" : "https://127.0.0.1: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" : "https://127.0.0.1:8080/people"
    },
    …
  }
}

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

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

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

当您导航到此存储库的 search 资源时,查找器方法的 @RestResource 注释已更改路径,如下所示

{
  "_links" : {
    "names" : {
      "href" : "https://127.0.0.1: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注释两个版本。