1. 程式人生 > >Spring Data REST不完全指南(二)

Spring Data REST不完全指南(二)

上一篇文章介紹了Spring Data REST的功能及特徵,以及演示瞭如何在專案中引入Spring Data REST並簡單地啟動演示了Spring Data REST專案。在本文中,我們將深入瞭解Spring Data REST的特性,以此來滿足我們日常api開發工作的要求。

如果僅僅是上一篇文章中對Spring Data REST的使用,那無法做到在日常開發中使用Spring Data REST,所以在上一篇文章中,我們列出了日常api開發中的一些必要功能:

需要滿足的一些要求:
1.針對欄位級別,方法級別,類級別進行限制(禁止某些欄位,方法,介面的對外對映)。
2.對資料增刪改查的限制(禁止某些請求方法的訪問)。
3.能個性化定義請求的路徑。
4.對所傳引數進行值校驗。
5.響應統一處理。
6.異常處理。
7.資料處理的切面。

➡️本文,將演示這些要求中的前三個要求。


針對介面級別,方法級別,欄位級別進行訪問限制

所謂的訪問限制,這裡我們的目的是指定某些資源不對外暴露,Spring Data REST使用註解來實現各級別的訪問限制。

介面級別的訪問限制:

@RepositoryRestResource(exported = false)
public interface TenantRepository extends CrudRepository<Tenant, Long> {
    Page<Tenant> findAllByNameContaining(String name, Pageable page);

    Page<Tenant> findAllByIdCardContaining(String idCard, Pageable page);

    Tenant findFirstByMobile(String mobile);

    Tenant findFirstByIdCard(String idCard);
}

Spring Data REST中我們在介面級別增加@RepositoryRestResource(exported = false)來實現介面及介面中的所有方法不對外暴露,從而限制訪問。

方法級別的訪問限制:

public interface TenantRepository extends CrudRepository<Tenant, Long> {
    Page<Tenant> findAllByNameContaining(String name, Pageable page);

    Page<Tenant> findAllByIdCardContaining(String idCard, Pageable page);

    Tenant findFirstByMobile(String mobile);

    @RestResource(exported = false)
    Tenant findFirstByIdCard(String idCard);
}

上述程式碼中,我們使用@RestResource(exported = false)註解在指定的方法上,從而實現該方法不對外暴露。

欄位級別的訪問限制

@Entity
@Data
@Accessors(chain = true)
public class Tenant {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    //隱私資訊不需要暴露
    @JsonIgnore
    private String idCard;

    private String mobile;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime rentDateTime;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private House house;

    public Tenant() {
    }

    public Tenant(String name, String idCard, String mobile, LocalDateTime rentDateTime, House hous) {
        this.name = name;
        this.idCard = idCard;
        this.mobile = mobile;
        this.rentDateTime = rentDateTime;
        this.house = hous;
    }
}

在上述程式碼中,我們在idCard欄位上增加了@JsonIgnore註解,從而實現該欄位不對外暴露。

如上圖,我們在HAL Browser中看到,輸出的租客資料中不再包含idCard欄位。

使用Projections和Excerpts來實現訪問限制

@Projection(name = "mobileAndName", types = {Tenant.class})
public interface TenantProjection {
    String getName();

    String getMobile();
}

如上,首先我們宣告一個投影(Projection),在上面的投影中,我們使用指定欄位的get方法來對外暴露需要暴露的欄位name,mobile。

此時,我們訪問HAL Browser

可以看到Spring Data REST此時提供了一個投影的連結。

此時我們查詢指定租客類的投影http://localhost:8080/tenants/1?projection=mobileAndName

{
  "name": "王一",
  "mobile": "186****3331",
  "_links": {
    "self": {
      "href": "http://localhost:8080/tenants/1"
    },
    "tenant": {
      "href": "http://localhost:8080/tenants/1{?projection}",
      "templated": true
    }
  }
}

可以看到只顯示了我們投影的欄位。

⚠️:我們宣告的投影介面需要和資料類在同一個包中。

⚠️:否則,我們需要增加配置類,來告訴Spring Data REST投影介面的位置,如下圖

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.getProjectionConfiguration().addProjection(TenantProjection.class);
    }

資料內聯

有時候,我們可能需要單獨對House類進行資料操作,所以我們會宣告一個HouseRepository

public interface HouseRepository extends CrudRepository<House, Long> {
}

此時,我們訪問某一租客資料(http://localhost:8080/tenants/1)時,

此時,house的資料就不會內聯在Tenant裡面。但是我們並不想要這種效果,我們希望house還是內聯在Tenant中的。我們可以使用Projection來解決此問題。

@Projection(name = "NameAndHouse", types = {Tenant.class})
public interface OnlyNameProjection {
    String getName();

    House getHouse();
}

如上,我們聲明瞭一個NameAndHouse投影。然後我們使用@RepositoryRestResource(excerptProjection = OnlyNameProjection.class)註解放在TenantRepository介面上。

@RepositoryRestResource(excerptProjection = OnlyNameProjection.class)
public interface TenantRepository extends CrudRepository<Tenant, Long> {
	...
}

此時,我們訪問NameAndHouse投影(http://localhost:8080/tenants/1?projection=NameAndHouse)

{
  "name": "王一",
  "house": {
    "houseNumber": "1101",
    "owner": "張三",
    "idCard": "330521******1"
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/tenants/1"
    },
    "tenant": {
      "href": "http://localhost:8080/tenants/1{?projection}",
      "templated": true
    },
    "house": {
      "href": "http://localhost:8080/tenants/1/house"
    }
  }
}

可以看到,House已經被內聯進Tenant中。


對資料增刪改查的限制

Spring Data REST提供了對資源請求的限制,比如對特定請求方法的限制,對特定資源訪問的限制。

Repository對外暴露限制

有時候我們希望,我們在Repository中定義的某些資料操作方法不對外暴露。Spring Data REST提供了了四個級別的資源限制級別:

  • ALL:公開所有Spring Data儲存庫,無論其Java可見性或註釋配置如何。
  • DEFAULT:公開公共Spring資料儲存庫或使用@RepositoryRestResource顯式註釋的儲存庫,並且其匯出屬性未設定為false。
  • VISIBILITY:無論註釋配置如何,僅公開公共Spring Data儲存庫。
  • ANNOTATED:僅公開使用@RepositoryRestResource顯式註釋的Spring Data儲存庫,並且其匯出屬性未設定為false。

如下程式碼實現了ANNOTATED級別的限制:

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED);
    }
}

增刪改查限制

在RESTful中定義:

GET(GET方法返回單個實體)

PUT(PUT方法用提供的請求主體替換目標資源的狀態(存在則修改,不存在則新建)。)

PATCH(PATCH方法類似於PUT方法,但是部分更新資源狀態。)

DELETE(刪除資訊)

所以所謂的對增刪改查的限制實際上就是對請求方法的限制。

如下,我們對Tenant類進行了兩個操作

  1. PUT操作禁止新增,但可以修改。
  2. DELETE限制,也就是限制了刪除操作。
@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        ExposureConfiguration exposureConfiguration = config.getExposureConfiguration();
        exposureConfiguration.forDomainType(Tenant.class)
                .disablePutForCreation()
                .withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.DELETE));
    }
}

如下為請求測試:

1.禁止DELETE請求

2.禁止PUT的新增操作

3.允許PUT的修改操作


個性化定義請求的路徑

Spring Data REST提供了個性化請求路徑的功能

自定義專案資源URI

預設情況下,專案資源的URI包含用於集合資源的路徑段,並附加了資料庫識別符號。這樣一來,您就可以使用儲存庫的findOne(…)方法來查詢實體例項。從Spring Data REST 2.5開始,可以通過使用RepositoryRestConfiguration上的配置API(在Java 8上首選)或通過將EntityLookup的實現註冊為應用程式中的Spring bean來自定義此屬性。 Spring Data REST會選擇它們並根據其實現來調整URI生成。

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.withEntityLookup()
                .forRepository(TenantRepository.class)
                .withIdMapping(Tenant::getMobile)
                .withLookup(TenantRepository::findFirstByMobile);
    }
}

如上,我們個性化地指定了Tenant的識別符號為mobile欄位,此時我們可以通過HAL Browser來看到路徑中的識別符號變成了mobile欄位。

配置REST URL路徑

我們使用@RepositoryRestResource@RestResource註解直接指定資源在路徑中的名字。

如下:

@RepositoryRestResource(path = "tenantPath")
public interface TenantRepository extends CrudRepository<Tenant, Long> {
    @RestResource(path = "mobile")
    Tenant findFirstByMobile(String mobile);
}

此時我們通過HAL Browser訪問此資源:

可以看到,被我們註解的findFirstByMobile對應的資源路徑已經被定製化。

另外我們看到"links"中的屬性名還是findFirstByMobile,我們可以通過@RestResource(path = "mobile",rel = "mobile")來個性化指定其名字,例如此註解中,我們指定了"links"中的findFirstByMobile屬性名為mobile。


總結

本文列出了介面開發常用的7個功能,並且演示如何實現針對介面級別,方法級別,欄位級別進行訪問限制,我們使用@RepositoryRestResource@RestResource@JsonIgnore分別實現介面,方法,欄位級別的訪問限制,並且我們利用了Projections和Excerpts來實現自定義資料格式。我們還是實現了對資料增刪改查的限制,我們通過RepositoryDetectionStrategy的四個級別來控制資料介面的對外暴露,使用ExposureConfiguration來限制某些資源對特定請求方式的限制。最後我們使用RepositoryRestConfiguration以及@RepositoryRestResource@RestResource註解實現了個性化定義請求的路徑。

本文程式碼示例:https://gitee.com/jeker8chen/spring-data-rest-in-practice.git


關注筆者公眾號,推送各類原創/優質技術文章 ⬇️

相關推薦

Spring Data REST完全指南

上一篇文章介紹了Spring Data REST的功能及特徵,以及演示瞭如何在專案中引入Spring Data REST並簡單地啟動演示了Spring Data REST專案。在本文中,我們將深入瞭解Spring Data REST的特性,以此來滿足我們日常api開發工作的要求。 如果僅僅是上一篇文章中對Sp

Spring Data REST完全指南

上一篇我們介紹了使用Spring Data REST時的一些高階特性,以及使用程式碼演示瞭如何使用這些高階的特性。本文將繼續講解前面我們列出來的七個高階特性中的後四個。至此,這些特效能滿足我們大部分的介面開發場景。 需要滿足的一些要求: 1.針對欄位級別,方法級別,類級別進行限制(禁止某些欄位,方法,介面的

Chrome開發者工具完全指南、進階篇

function a () { b(); } function b() { c(); } function c() { //在該處斷點,檢視call stack } a->b->c. call stack 從上到下的順序就是 c

Spring-data-jpa:學習筆記

       通過上一篇筆記的,我們掌握了SpringData的相關概念及簡單的用法。但上一篇筆記主要講的是Dao層介面直接繼承Repository介面,然後再自己定義方法。主要闡述了自定義方法時的一些規則及SpringData是如何

ngular6開發完全筆記-- 管道

課程 tst 考試 一個 tor 點擊 裏的 ive scribe 自定義管道 管道(過濾器)為過濾數據顯示下列list數據 pip.ts 文件 import { Pipe, PipeTransform } from '@angular/core';

GO語言web框架Gin之完全指南

這篇主要講解自定義日誌與資料驗證 引數驗證 我們知道,一個請求完全依賴前端的引數驗證是不夠的,需要前後端一起配合,才能萬無一失,下面介紹一下,在Gin框架裡面,怎麼做介面引數驗證的呢 gin 目前是使用 go-playground/validator 這個框架,截止目前,預設是使用 v10 版本;具體用法可以

Spring Boot中使用WebSocket總結:向指定使用者傳送WebSocket訊息並處理對方線上的情況

Spring Boot中使用WebSocket總結(二):向指定使用者傳送WebSocket訊息並處理對方不線上的情況 在上一篇文章(www.zifangsky.cn/1355.html)中我介紹了在Spring專案中使用WebSocket的幾種實現方式。但是,上篇文章中只介紹了服務端採用廣播模式給所有客戶

Chrome開發者工具完全指南四、效能進階篇

前言   Profiles面板功能的作用主要是監控網頁中各種方法執行時間和記憶體的變化,簡單來說它就是Timeline的數字化版本。它的功能選項卡不是很多(只有三個),操作起來比較前面的幾塊功能版本來說簡單,但是裡面的資料確很多,很雜,要弄懂它們需要花費一些時間。尤其是在記憶體快照中的各種龐雜的資料。在這篇

Chrome開發者工具完全指南五、移動篇

  前面介紹了Chrome開發者工具的大部分內容工具,現在介紹最後兩塊功能Audits和Console面板。一、Audits  Audits面板會針對目前網頁提出若干條優化的建議,這些建議分為兩大類,一類是網路載入效能,另一類是介面效能。首先開下它的主介面。  Audits面板的網路優化建議參照的是雅虎前端工

Chrome開發者工具完全指南一、基礎功能篇

  就算你不是一名前端開發工程師,相信你也不會對Chrome瀏覽器感到陌生。根據最新的一份(2015/06)的瀏覽器市場佔有率報告,Chrome近乎佔有瀏覽器天下的半壁江山。簡單、快捷使它成為了新時代人們的新寵。如果你是一名web開發人員,我推薦你使用Chrome。作為前端開發的"IDE",你只需要搭配一個編

Spring data jpa 多表查詢:多表動態條件查詢

上一章說完單表動態條件查詢,這章就說下多表關聯查詢 1、先說一對多關係,就以上一章的A模型和B模型,為例 A 對應 多個 B,而現在需求就是查詢A和B關聯,並需要傳入的動態引數,可能是A模型中的屬性,也有可能是B模型中的引數 還是用虛擬碼來說明,並且用的是Specifi

Spring Cloud Alibaba遷移指南:零程式碼替換 Eureka

自 Spring Cloud 官方宣佈 Spring Cloud Netflix

Spring Cloud Alibaba遷移指南:零代碼替換 Eureka

關於 lis maven lee work 啟動 默認 hystrix alibaba 自 Spring Cloud 官方宣布 Spring Cloud Netflix 進入維護狀態後,我們開始制作《Spring Cloud Alibaba遷移指南》系列文章,向開發者提供更

spring 加密 Druid 連接池—— 加密 url,driverClassName,用戶名,密碼

stack urn b- ride style alibaba row com logs why? 連接信息暴露在配置文件中有風險 how? 一、準備加密後連接信息 使用Druid自帶工具類ConfigTools加密連接信息 import com.alibaba.dr

Spring MVC 的 研發之路

eight 對象 files tin servlet映射 資源 研發 領域 延遲 二、web.xml的簡單配置介紹1 1、啟動Web項目時,容器回去讀web.xml配置文件裏的兩個節點<context-param>和<listener

Spring Boot 揭秘與實戰 數據存儲篇 - 聲明式事務管理

public rollback long tar jpa oid config 新的 autowire 文章目錄 1. 聲明式事務 2. Spring Boot默認集成事務 3. 實戰演練4. 源代碼 3.1. 實體對象 3.2. DAO 相關 3.3. Service

Spring Data 關於Repository的介紹

聲明 except int pre dcl import type esc return Repository類的定義: public interface Repository<T, ID extends Serializable> { } 1)Rep

android源碼編譯——從此走上Liunx的歸路

彈出 oid log 按鈕 鍵盤 點擊 使用 andro android Ubuntu安裝:   1.啟動虛擬機進入到如下界面:         2.下拉找到“中文(簡體)”選項,然後選擇“安裝Ubuntu”:         3.點擊繼續:         4.選擇清除整

Maven入門指南

deploy ... web服務器 快速 repos 必須 轉載 關於 net 轉載自並發編程網 – ifeve.com本文鏈接地址: Maven入門指南(二) Maven目錄結構 Maven有一個標準的目錄結構。如果你在項目中遵循Maven的目錄結構,就無需在pom文件中

Spring Boot幹貨系列:配置文件解析

set test profile ava java prefix 標註 了解 pre Spring Boot:配置文件解析 前言 上一篇介紹了Spring Boot的入門,知道了Spring Boot使用“習慣優於配置”(項目中存在大量的配置,此外