Spring Data REST


1.REST(Representational State Transfer)

用來規范應用如何在 HTTP 層與 API 提供方進行數據交互

REST約束

1.客戶端-服務器結構
2.無狀態
3.可緩存
4.分層的系統
5.按需代碼(可選)
6.統一接口。
  該約束是 REST 服務的基礎,是客戶端和服務器之間的橋梁。該約束又包含下面
4個子約束:     資源標識符。每個資源都有各自的標識符。客戶端在請求時需要指定該標識符。在 REST 服務中,該標識符通常是 URI。客戶端所獲取的是資源的表達(representation),通常使用 XML 或 JSON 格式。     通過資源的表達來操縱資源。客戶端根據所得到的資源的表達中包含的信息來了解如何操縱資源,比如對資源進行修改或刪除。     自描述的消息。每條消息都包含足夠的信息來描述如何處理該消息。     超媒體作為應用狀態的引擎(HATEOAS)。客戶端通過服務器提供的超媒體內容中動態提供的動作來進行狀態轉換。

2.HATEOAS(The Hypermedia As The Engine Of Application Statue)

是REST架構的主要約束

REST成熟的模型

第一個層次(Level 0)的 Web 服務只是使用 HTTP 作為傳輸方式,實際上只是遠程方法調用(RPC)的一種具體形式。SOAP 和 XML-RPC 都屬於此類。
第二個層次(Level 1)的 Web 服務引入了資源的概念。每個資源有對應的標識符和表達。
第三個層次(Level 2)的 Web 服務使用不同的 HTTP 方法來進行不同的操作,並且使用 HTTP 狀態碼來表示不同的結果。如 HTTP GET 方法來獲取資源,HTTP DELETE 方法來刪除資源。
第四個層次(Level 3)的 Web 服務使用 HATEOAS。在資源的表達中包含了鏈接信息。客戶端可以根據鏈接來發現可以執行的動作。

根據REST 成熟度模型中可以看到,使用 HATEOAS 的 REST 服務是成熟度最高的,也是推薦的做法

RESTful API最好做到Hypermedia,或HATEOAS,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什么

eg:

{ 
    "links": { 
     "self": { "href": "http://api.com/items" }, 
     "item": [ 
      { "href": "http://api.com/items/1" }, 
      { "href": "http://api.com/items/2" } 
     ] 
    "data": [ 
      {"itemName":"a"}, 
      {"itemName":"b"} 
    ] 
} 

3.HAL(Hypertext Application Language)

HAL是一種簡單的格式,為 API 中的資源提供簡單一致的鏈接

HAL可以用來實現HATEOAS

HAL 模型包括:

鏈接

內嵌資源

狀態

 HAL專為構建API而設計,在這些API中,客戶端通過以下鏈接在客戶端中瀏覽資源

4.spring-boot-starter-data-rest使用Spring Boot構建RESTful API

Spring Data REST是基於Spring Data的repository之上,可以把 repository 自動輸出為REST資源

Spring Data REST把我們需要編寫的大量REST模版接口做了自動化實現,並符合HAL的規范
(1)添加依賴

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>

(2)示例

實體類User

package com.example.demo.model;

import lombok.*;
import org.hibernate.annotations.CreationTimestamp;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "users")
@Data
@Builder
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    @Column(updatable = false)
    @CreationTimestamp
    private Date createTime;
}
View Code

UsersRepository

package com.example.demo.repository;

import com.example.demo.model.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UsersRepository extends JpaRepository<Users,Integer> {
}
View Code

這樣就已經提供了一個關於user的rest api,簡單的增、刪、改、查都有了。不用寫Controller,spring已經實現了

啟動項目

GET  http://127.0.0.1:8080

{
  "_links": {
    "userses": {
      "href": "http://127.0.0.1:8080/userses{?page,size,sort}",
      "templated": true
    },
    "profile": {
      "href": "http://127.0.0.1:8080/profile"
    }
  }
}

分頁+排序查詢

GET  http://127.0.0.1:8080/userses?page=1&size=2&sort=createTime

{
  "_embedded": {
    "userses": [
      {
        "name": "Nana",
        "createTime": "2020-04-07T02:10:12.469+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/userses/5"
          },
          "users": {
            "href": "http://127.0.0.1:8080/userses/5"
          }
        }
      },
      {
        "name": "xyz",
        "createTime": "2020-04-07T02:10:12.469+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/userses/3"
          },
          "users": {
            "href": "http://127.0.0.1:8080/userses/3"
          }
        }
      }
    ]
  },
  "_links": {
    "first": {
      "href": "http://127.0.0.1:8080/userses?page=0&size=2&sort=createTime,asc"
    },
    "prev": {
      "href": "http://127.0.0.1:8080/userses?page=0&size=2&sort=createTime,asc"
    },
    "self": {
      "href": "http://127.0.0.1:8080/userses"
    },
    "next": {
      "href": "http://127.0.0.1:8080/userses?page=2&size=2&sort=createTime,asc"
    },
    "last": {
      "href": "http://127.0.0.1:8080/userses?page=2&size=2&sort=createTime,asc"
    },
    "profile": {
      "href": "http://127.0.0.1:8080/profile/userses"
    }
  },
  "page": {
    "size": 2,
    "totalElements": 5,
    "totalPages": 3,
    "number": 1
  }
}

查詢某一個

GET  http://127.0.0.1:8080/userses/5

{
  "name": "Nana",
  "createTime": "2020-04-07T02:10:12.469+0000",
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/userses/5"
    },
    "users": {
      "href": "http://127.0.0.1:8080/userses/5"
    }
  }
}

新增

POST  http://127.0.0.1:8080/userses

 

 修改

PUT  http://127.0.0.1:8080/userses/481

 

 刪除

DELETE   http://127.0.0.1:8080/userses/481

(3)其他

注解 @RepositoryRestResource指定切入點

eg:

  映射到 /user上

  添加自定義查詢

    findByName

    findByNameContaining

package com.example.demo.repository;

import com.example.demo.model.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.stereotype.Repository;

import java.util.List;

@RepositoryRestResource(collectionResourceRel = "user", path = "user")
public interface UsersRepository extends JpaRepository<Users,Integer> {
    List<Users> findByName(@Param("name") String name);
    List<Users> findByNameContaining(@Param("name") String name);
}

注:

  方法的定義,參數要有 @Param 注解

重新啟動項目

GET  http://127.0.0.1:8080/user

{
  "_embedded": {
    "user": [
      {
        "name": "Lili",
        "createTime": "2020-04-07T02:50:27.501+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/1"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/1"
          }
        }
      },
      {
        "name": "Fiona",
        "createTime": "2020-04-07T02:50:27.508+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/2"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/2"
          }
        }
      },
      {
        "name": "xyz",
        "createTime": "2020-04-07T02:50:27.508+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/3"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/3"
          }
        }
      }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/user{?page,size,sort}",
      "templated": true
    },
    "profile": {
      "href": "http://127.0.0.1:8080/profile/user"
    },
    "search": {
      "href": "http://127.0.0.1:8080/user/search"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 5,
    "totalPages": 1,
    "number": 0
  }
}

GET  http://127.0.0.1:8080/user/search

{
  "_links": {
    "findByNameContaining": {
      "href": "http://127.0.0.1:8080/user/search/findByNameContaining{?name}",
      "templated": true
    },
    "findByName": {
      "href": "http://127.0.0.1:8080/user/search/findByName{?name}",
      "templated": true
    },
    "self": {
      "href": "http://127.0.0.1:8080/user/search"
    }
  }
}

查詢 name=xyz

GET http://127.0.0.1:8080/user/search/findByName?name=xyz

{
  "_embedded": {
    "user": [
      {
        "name": "xyz",
        "createTime": "2020-04-07T03:14:11.921+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/3"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/3"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/user/search/findByName?name=xyz"
    }
  }
}

查詢 name 包含i的

GET http://127.0.0.1:8080/user/search/findByNameContaining?name=i

{
  "_embedded": {
    "user": [
      {
        "name": "Lili",
        "createTime": "2020-04-07T03:14:11.913+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/1"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/1"
          }
        }
      },
      {
        "name": "Fiona",
        "createTime": "2020-04-07T03:14:11.920+0000",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/2"
          },
          "users": {
            "href": "http://127.0.0.1:8080/user/2"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/user/search/findByNameContaining?name=i"
    }
  }
}

配置

在application.properties 中配置

給所有的接口添加統一的前綴

spring.data.rest.base-path=/rest

添加/更新成功時是否返回添加/更新記錄

spring.data.rest.return-body-on-create=true
spring.data.rest.return-body-on-update=true

注:

  如果為false,則返回空白

 

 

 

 

 

 

 


免責聲明!

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



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