配置 REST URL 路徑

您可以配置匯出 JPA repository 資源的 URL 路徑段。為此,請在類級別或查詢方法級別添加註解。

預設情況下,匯出器使用域類的名稱來暴露您的 CrudRepository。Spring Data REST 還會應用 Evo Inflector 來將此詞複數化。考慮以下 repository 定義

interface PersonRepository extends CrudRepository<Person, Long> {}

上述示例定義的 repository 在 localhost:8080/persons/ 處暴露。

要更改 repository 的匯出方式,請在類級別新增 @RestResource 註解,如下例所示

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

上述示例定義的 repository 可在 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://: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://:8080/persons/search/names"
    }
  }
}
這些 JSON 片段假設您使用 Spring Data REST 的預設格式 HAL。您可以關閉 HAL,這將導致輸出看起來不同。然而,您覆蓋 rel 名稱的能力完全獨立於渲染格式。

您可以更改 repository 的 rel,如下例所示

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

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

更改 repository 的 rel 會改變頂級名稱,如下例輸出所示

{
  "_links" : {
    "people" : {
      "href" : "https://:8080/people"
    },
    …
  }
}

在上述輸出所示的頂級片段中

  • path = "people"href 中的值從 /persons 更改為 /people

  • rel = "people" 將該連結的名稱從 persons 更改為 people

當您導航到此 repository 的 search 資源時,finder 方法的 @RestResource 註解已改變了路徑,如下所示

{
  "_links" : {
    "names" : {
      "href" : "https://:8080/people/search/names"
    }
  }
}

您的 repository 定義中的這組註解導致了以下更改

  • Repository 級別註解的 path = "people" 體現在基礎 URI 中,顯示為 /people

  • 包含 finder 方法為您提供了 /people/search

  • path = "names" 建立了一個 URI /people/search/names

  • rel = "names" 將該連結的名稱從 findByNames 更改為 names

隱藏特定的 Repositories、查詢方法或欄位

您可能不希望某個 repository、repository 上的某個查詢方法或實體的某個欄位被匯出。例如,隱藏 User 物件上的 password 等敏感欄位。要告知匯出器不匯出這些項,請使用 @RestResource 註解它們並設定 exported = false

例如,要跳過匯出某個 repository,您可以建立一個類似於以下示例的 repository 定義

@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;
}
Projections 提供了一種方法來改變匯出內容,並有效地 繞過這些設定。如果您針對同一個域物件建立了任何 projections,請務必不要匯出這些欄位。

隱藏 Repository CRUD 方法

如果您不想在 CrudRepository 上暴露 save 或 delete 方法,您可以透過覆蓋想要關閉的方法並在被覆蓋的版本上放置 @RestResource(exported = false) 設定來實現。例如,為了阻止 HTTP 使用者呼叫 CrudRepository 的 delete 方法,請覆蓋所有這些方法並在被覆蓋的方法上添加註解,如下所示

@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 註解這兩個版本。