配置 REST URL 路径

您可以配置 JPA 仓库资源导出所对应的 URL 路径段。为此,可在类级别或查询方法级别添加注解。spring-doc.cadn.net.cn

默认情况下,导出器会使用领域类的名称来暴露您的 CrudRepository。Spring Data REST 还会应用 Evo Inflector 对该单词进行复数化处理。请考虑以下仓库定义:spring-doc.cadn.net.cn

interface PersonRepository extends CrudRepository<Person, Long> {}

前面示例中定义的仓库在 localhost:8080/persons/ 上公开。spring-doc.cadn.net.cn

要更改仓库的导出方式,请在类级别添加一个 @RestResource 注解,如下例所示:spring-doc.cadn.net.cn

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

前面示例中定义的仓库可通过 localhost:8080/people/ 访问。spring-doc.cadn.net.cn

如果你定义了查询方法,这些方法默认也会以其名称进行暴露,如下例所示:spring-doc.cadn.net.cn

interface PersonRepository extends CrudRepository<Person, Long> {

  List<Person> findByName(String name);
}
所有查询方法资源都通过 search 资源公开。

要更改此查询方法所暴露的 URL 路径段,您可以再次使用 @RestResource 注解,如下例所示:spring-doc.cadn.net.cn

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

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

现在,前面示例中的查询方法已暴露在 localhost:8080/people/search/namesspring-doc.cadn.net.cn

处理rel属性

由于这些资源都是可发现的,你还可以控制导出器发出的链接中 rel 属性的显示方式。spring-doc.cadn.net.cn

例如,在默认配置下,如果你向 localhost:8080/persons/search 发起一个请求以查看有哪些查询方法被公开,你将收到一个类似如下的链接列表:spring-doc.cadn.net.cn

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

要更改 rel 值,请在 rel 注解上使用 @RestResource 属性,如下例所示:spring-doc.cadn.net.cn

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

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

前面的示例将生成以下链接值:spring-doc.cadn.net.cn

{
  "_links" : {
    "names" : {
      "href" : "http://localhost:8080/persons/search/names"
    }
  }
}
这些 JSON 片段假设你使用了 Spring Data REST 的默认格式 HAL。你可以关闭 HAL,这将导致输出看起来有所不同。然而,你覆盖 rel 名称的能力完全独立于渲染格式。

你可以更改仓库的 rel,如下例所示:spring-doc.cadn.net.cn

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

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

更改仓库的 rel 会改变顶层名称,如下例所示:spring-doc.cadn.net.cn

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

在前面输出所示的顶层片段中:spring-doc.cadn.net.cn

当你导航到该仓库的 search 资源时,查找方法的 @RestResource 注解已修改了路径,如下所示:spring-doc.cadn.net.cn

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

您的仓库定义中的这组注解已导致以下更改:spring-doc.cadn.net.cn

隐藏特定的存储库、查询方法或字段

你可能不希望某个仓库、仓库中的某个查询方法,或者实体的某个字段被导出。例如,在 password 对象中隐藏 User 等敏感字段就属于此类情况。要告知导出器不要导出这些项,请使用 @RestResource 注解并将 exported = false 设置为 false。spring-doc.cadn.net.cn

例如,若要跳过导出某个仓库,您可以创建一个类似于以下示例的仓库定义:spring-doc.cadn.net.cn

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

要跳过导出某个查询方法,可以使用 @RestResource(exported = false) 注解该查询方法,如下所示:spring-doc.cadn.net.cn

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

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

同样地,若要跳过某个字段的导出,您可以使用 @RestResource(exported = false) 注解该字段,如下所示:spring-doc.cadn.net.cn

@Entity
public class Person {

  @Id @GeneratedValue private Long id;

  @OneToMany
  @RestResource(exported = false)
  private Map<String, Profile> profiles;
}
投影(Projections)提供了一种方式,用于更改导出的内容,并有效地绕过这些设置。如果你针对同一领域对象创建了任何投影,请务必不要导出字段。

隐藏 Repository CRUD 方法

如果你不想在你的 CrudRepository 上暴露 save 或 delete 方法,可以通过重写你想要禁用的方法,并在重写后的方法上添加 @RestResource(exported = false) 注解来实现。例如,为了防止 HTTP 用户调用 CrudRepository 的 delete 方法,你可以重写所有这些方法,并在重写后的方法上添加该注解,如下所示:spring-doc.cadn.net.cn

@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