RESTful ,到現在相信已經沒人不知道這個東西了吧!關於 RESTful 的概念,我這裡就不做過多介紹了,傳統的 Struts 對 RESTful 支援不夠友好 ,但是 SpringMVC 對於 RESTful 提供了很好的支援,常見的相關注解有:
@RestController
@GetMapping
@PutMapping
@PostMapping
@DeleteMapping
@ResponseBody
...
這些註解都是和 RESTful 相關的,在移動網際網路中,RESTful 得到了非常廣泛的使用。RESTful 這個概念提出來很早,但是以前沒有移動網際網路時,我們做的大部分應用都是前後端不分的,在這種架構的應用中,資料基本上都是在後端渲染好返回給前端展示的,此時 RESTful 在 Web 應用中基本就沒用武之地,移動網際網路的興起,讓我們一套後臺對應多個前端專案,因此前後端分離,RESTful 順利走上前臺。
Spring Boot 繼承自 Spring + SpringMVC, SpringMVC 中對於 RESTful 支援的特性在 Spring Boot 中全盤接收,同時,結合 Jpa 和 自動化配置,對於 RESTful 還提供了更多的支援,使得開發者幾乎不需要寫程式碼(很少幾行),就能快速實現一個 RESTful 風格的增刪改查。
接下來,鬆哥通過一個簡單的案例,來向大家展示 Spring Boot 對於 RESTful 的支援。
實戰
建立工程
首先建立一個 Spring Boot 工程,引入 Web
、 Jpa
、 MySQL
、Rest Repositories
依賴:
建立完成後,還需要鎖定 MySQL 驅動的版本以及加入 Druid 資料庫連線池,完整依賴如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>5.1.27</version>
</dependency>
</dependencies>
配置資料庫
主要配置兩個,一個是資料庫,另一個是 Jpa:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql:///test01
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=mysql
spring.jpa.database=mysql
這裡的配置,和 Jpa 中的基本一致。
前面五行配置了資料庫的基本資訊,包括資料庫連線池、資料庫使用者名稱、資料庫密碼、資料庫連線地址以及資料庫驅動名稱。
接下來的五行配置了 JPA 的基本資訊,分別表示生成 SQL 的方言、列印出生成的 SQL 、每次啟動專案時根據實際情況選擇是否更新表、資料庫平臺是 MySQL。
這兩段配置是關於 MySQL + JPA 的配置,沒用過 JPA 的小夥伴可以參考鬆哥之前的 JPA 文章:http://www.javaboy.org/2019/0407/springboot-jpa.html
構建實體類
@Entity(name = "t_book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "book_name")
private String name;
private String author;
//省略 getter/setter
}
public interface BookRepository extends JpaRepository<Book,Long> {
}
這裡一個是配置了一個實體類 Book,另一個則是配置了一個 BookRepository ,專案啟動成功後,框架會根據 Book 類的定義,在資料庫中自動建立相應的表,BookRepository 介面則是繼承自 JpaRepository ,JpaRepository 中自帶了一些基本的增刪改查方法。
好了,程式碼寫完了。
啥?你好像啥都沒寫啊?是的,啥都沒寫,啥都不用寫,一個 RESTful 風格的增刪改查應用就有了,這就是 Spring Boot 的魅力!
測試
此時,我們就可以啟動專案進行測試了,使用 POSTMAN 來測試(大家也可以自行選擇趁手的 HTTP 請求工具)。
此時我們的專案已經預設具備了一些介面,我們分別來看:
根據 id 查詢介面
- http://127.0.0.1:8080/books/{id}
這個介面表示根據 id 查詢某一本書:
分頁查詢
- http://127.0.0.1:8080/books
這是一個批量查詢介面,預設請求路徑是類名首字母小寫,並且再加一個 s 字尾。這個介面實際上是一個分頁查詢介面,沒有傳引數,表示查詢第一頁,每頁 20 條資料。
查詢結果中,除了該有的資料之外,也包含了分頁資料:
分頁資料中:
- size 表示每頁查詢記錄數
- totalElements 表示總記錄數
- totalPages 表示總頁數
- number 表示當前頁數,從0開始計
如果要分頁或者排序查詢,可以使用 _links 中的連結。http://127.0.0.1:8080/books?page=1&size=3&sort=id,desc
。
新增
也可以新增資料,新增是 POST 請求,資料通過 JSON 的形式傳遞,如下:
新增成功之後,預設會返回新增成功的資料。
修改
修改介面預設也是存在的,資料修改請求是一個 PUT 請求,修改的引數也是通過 JSON 的形式傳遞:
預設情況下,修改成功後,會返回修改成功的資料。
刪除
當然也可以通過 DELETE 請求根據 id 刪除資料:
刪除成功後,是沒有返回值的。
不需要幾行程式碼,一個基本的增刪改查就有了。
這些都是預設的配置,這些預設的配置實際上都是在 JpaRepository 的基礎上實現的,實際專案中,我們還可以對這些功能進行定製。
查詢定製
最廣泛的定製,就是查詢,因為增刪改操作的變化不像查詢這麼豐富。對於查詢的定製,非常容易,只需要提供相關的方法即可。例如根據作者查詢書籍:
public interface BookRepository extends JpaRepository<Book,Long> {
List<Book> findBookByAuthorContaining(@Param("author") String author);
}
注意,方法的定義,引數要有 @Param 註解。
定製完成後,重啟專案,此時就多了一個查詢介面,開發者可以通過 http://localhost:8080/books/search 來檢視和 book 相關的自定義介面都有哪些:
查詢結果表示,只有一個自定義介面,介面名就是方法名,而且查詢結果還給出了介面呼叫的示例。我們來嘗試呼叫一下自己定義的查詢介面:
開發者可以根據實際情況,在 BookRepository 中定義任意多個查詢方法,查詢方法的定義規則和 Jpa 中一模一樣(不懂 Jpa 的小夥伴,可以參考乾貨|一文讀懂 Spring Data Jpa!,或者在鬆哥個人網站 www.javaboy.org 上搜尋 JPA,有相關教程參考)。但是,這樣有一個缺陷,就是 Jpa 中方法名太長,因此,如果不想使用方法名作為介面名,則可以自定義介面名:
public interface BookRepository extends JpaRepository<Book, Long> {
@RestResource(rel = "byauthor",path = "byauthor")
List<Book> findBookByAuthorContaining(@Param("author") String author);
}
@RestResource 註解中,兩個引數的含義:
- rel 表示介面查詢中,這個方法的 key
- path 表示請求路徑
這樣定義完成後,表示介面名為 byauthor ,重啟專案,繼續查詢介面:
除了 rel
和 path
兩個屬性之外,@RestResource
中還有一個屬性,exported
表示是否暴露介面,預設為 true
,表示暴露介面,即方法可以在前端呼叫,如果僅僅只是想定義一個方法,不需要在前端呼叫這個方法,可以設定 exported
屬性為 false
。
如果不想暴露官方定義好的方法,例如根據 id
刪除資料,只需要在自定義介面中重寫該方法,然後在該方法上加 @RestResource
註解並且配置相關屬性即可。
public interface BookRepository extends JpaRepository<Book, Long> {
@RestResource(rel = "byauthor",path = "byauthor")
List<Book> findBookByAuthorContaining(@Param("author") String author);
@Override
@RestResource(exported = false)
void deleteById(Long aLong);
}
另外生成的 JSON 字串中的集合名和單個 item
的名字都是可以自定義的:
@RepositoryRestResource(collectionResourceRel = "bs",itemResourceRel = "b",path = "bs")
public interface BookRepository extends JpaRepository<Book, Long> {
@RestResource(rel = "byauthor",path = "byauthor")
List<Book> findBookByAuthorContaining(@Param("author") String author);
@Override
@RestResource(exported = false)
void deleteById(Long aLong);
}
path
屬性表示請求路徑,請求路徑預設是類名首字母小寫+s,可以在這裡自己重新定義。
其他配置
最後,也可以在 application.properties 中配置 REST 基本引數:
spring.data.rest.base-path=/api
spring.data.rest.sort-param-name=sort
spring.data.rest.page-param-name=page
spring.data.rest.limit-param-name=size
spring.data.rest.max-page-size=20
spring.data.rest.default-page-size=0
spring.data.rest.return-body-on-update=true
spring.data.rest.return-body-on-create=true
配置含義,從上往下,依次是:
- 給所有的介面新增統一的字首
- 配置排序引數的 key ,預設是 sort
- 配置分頁查詢時頁碼的 key,預設是 page
- 配置分頁查詢時每頁查詢頁數的 key,預設是size
- 配置每頁最大查詢記錄數,預設是 20 條
- 分頁查詢時預設的頁碼
- 更新成功時是否返回更新記錄
- 新增成功時是否返回新增記錄
總結
本文主要向大家介紹了 Spring Boot 中快速實現一個 RESTful 風格的增刪改查應用的方案,整體來說還是比較簡單的,並不難。相關案例我已上傳到 GitHub 上了,小夥伴可以自行下載:https://github.com/lenve/javaboy-code-samples。
關於本文,有問題歡迎留言討論。
關注公眾號牧碼小子,專注於 Spring Boot+微服務,定期視訊教程分享,關注後回覆 Java ,領取鬆哥為你精心準備的 Java 乾貨!