Spring Data REST不完全指南(一)


簡介

Spring Data REST是Spring Data項目的一部分,可輕松在Spring Data存儲庫上構建超媒體驅動的REST Web服務。

Spring Data REST 構建在 Spring 數據存儲庫之上,分析應用程序的域模型,並公開模型中包含的聚合的超媒體驅動的 HTTP 資源。

特征:

  • 使用 HAL 媒體類型來公開域模型的 REST API。
  • 適用集合、項目(item)和關聯資源表示你的模型。
  • 通過鏈接導航支持分頁。
  • 允許動態過濾收集資源。
  • 通過資源api來暴露你repositories中定義的資源查詢方法。
  • 允許通過處理Spring ApplicationEvents來處理REST請求。
  • 公開有關ALPS和JSON Schema模型的元數據。
  • 允許通過投影定義客戶特定的表示形式。
  • 發布一個定制的HAL瀏覽器變體以利用公開的元數據。
  • 目前支持JPA,MongoDB,Neo4j,Solr,Cassandra,Gemfire。
  • 允許對公開的默認資源進行高級自定義。

💡:目前對Spring Data REST適用分析:快速生成數據庫資源對外的接口(適用於一些邏輯簡單的數據對外接口)


分析

使用Spring Data REST並實現以下功能來滿足日常api的開發過程:

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

以上列出了我們日常接口開發中比較常見的一些功能需求,這里將演示使用Spring Data REST並結合實現上述功能來快速開發HAL REST API。


准備

條件:

jdk11

Springboot 2.2.6.RELEASE

maven

Spring Data JPA

添加依賴

本文中演示Spring Data JPA結合Spring Data REST

1.添加Spring Data持久層依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
 <dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
</dependency>

目前Spring Data REST支持JPA,MongoDB,Neo4j,Solr,Cassandra,Gemfire,所以使用時可根據自己的需求引入不同的Spring Data依賴,本文將使用JPA作為演示。

2.添加Spring Data REST相關依賴

<!--Spring Data REST-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<!--Spring Data REST 數據瀏覽工具-->
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>

簡單嘗試

示例中將用一個簡單的租客系統來做演示。

創建一個房子類

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

    private String houseNumber;

    private String owner;

    private String idCard;

    public House() {
    }

    public House(String houseNumber, String owner, String idCard) {
        this.houseNumber = houseNumber;
        this.owner = owner;
        this.idCard = idCard;
    }
}

創建一個租客類

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

    private String name;

    //隱私信息不需要暴露
    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;
    }
}

此時,我們新建一個租客的Reopsitory

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);
}

運行前我們准備好初始化數據

@SpringBootApplication
public class SpringDataRestDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringDataRestDemoApplication.class, args);
    }

    @Resource
    private TenantRepository tenantRepository;

    @PostConstruct
    public void initRepo() {
        //准備房子信息
        List<House> houses = new ArrayList<>();
        House zhangsan = new House("1101", "張三", "330521******1");
        House zhangsi = new House("1102", "張四", "330521******2");
        House zhangwu = new House("1103", "張五", "330521******3");
        House zhangliu = new House("1104", "張六", "330521******4");
        House zhangqi = new House("1105", "張七", "330521******5");
        House zhangba = new House("1106", "張八", "330521******6");
        //准備租客信息
        List<Tenant> tenants = new ArrayList<>();
        tenants.add(new Tenant("王一", "330522******1", "186****3331", LocalDateTime.now().minusDays(1), zhangsan));
        tenants.add(new Tenant("王二", "330522******2", "186****3332", LocalDateTime.now().minusDays(2), zhangsi));
        tenants.add(new Tenant("王三", "330522******3", "186****3333", LocalDateTime.now().minusDays(3), zhangwu));
        tenants.add(new Tenant("王四", "330522******4", "186****3334", LocalDateTime.now().minusDays(4), zhangliu));
        tenants.add(new Tenant("王五", "330522******5", "186****3335", LocalDateTime.now().minusDays(5), zhangqi));
        tenants.add(new Tenant("王六", "330522******6", "186****3336", LocalDateTime.now().minusDays(6), zhangba));
        tenantRepository.saveAll(tenants);
    }
}

啟動項目,並且訪問localhost:8080,如下圖:

image-20200420130723041

上圖是Spring Data REST的HAL數據瀏覽器,通過它能高效的查詢和調試Spring Data REST對外提供的接口。

我們可以看到響應內容的格式,正是符合HAL類型的格式。

訪問http://localhost:8080/tenants/search

image-20200420133931527

上圖可以看到,Spring Data REST對外暴露了我們在Repository中定義的查詢方法,並且可以看到response Body中數據格式符合HAL格式類型,通過HAL格式的響應數據,我們輕松就能知道這些查詢方法對應的請求路徑,起到了一個文檔的作用,使api能夠自發現。


總結

本文初步的介紹了Spring Data REST的功能及特征,並且演示了如何在項目中引入Spring Data REST,並結合Spring Data REST實現了簡單的演示Demo。下一篇文章將介紹並演示如何在Spring Data REST中實現一些必要的功能,以此來滿足我們日常的接口開發工作。

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


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM