基于SpringBoot打造RESTful API實(shí)戰(zhàn)指南
一、什么是 RESTful API?
REST(Representational State Transfer)是一種 面向資源 的架構(gòu)風(fēng)格,核心思想:
用 URL 定位資源,用 HTTP 動(dòng)詞描述操作
面向資源怎么理解呢?:
RESTful API 就是符合 REST 約束的接口,特點(diǎn):
- ? 無狀態(tài)(每次請求自帶上下文)
- ? 統(tǒng)一接口(GET/POST/PUT/DELETE)
- ? 資源導(dǎo)向(URL 是名詞,不是動(dòng)詞)
二、設(shè)計(jì)規(guī)范
2.1 controller接口設(shè)計(jì)規(guī)范
RESTful API的RequestMapping的方式有4種,以圖書為例,每一種的應(yīng)用場景如下:
| 動(dòng)作 | 資源集合 /books | 單個(gè)資源 /books/{id} |
| GET | 查詢集合 | 查詢單個(gè) |
| POST | 新增集合 | ? |
| PUT | 批量更新 | 更新單個(gè) |
| DELETE | 批量刪除 | 刪除單個(gè) |
2.2 返回結(jié)構(gòu)設(shè)計(jì)規(guī)范
| 字段 | 類型 | 說明 |
| code | int | HTTP 狀態(tài)碼(200/400/404/500) |
| message | string | 用戶可讀提示信息 |
| data | 泛型T | 業(yè)務(wù)數(shù)據(jù)(含分頁) |
三、restful與非restful風(fēng)格對比
3.1查詢圖書
非 RESTful 代碼:
@GetMapping("/getBook")
public List<Book> getBooks(@RequestParam int page,@RequestParam int size) {
return bookService.list(page,size); // 直接 List
}RESTful 代碼:
@GetMapping("/book")
public ApiResponse<PageVO<Book>> list(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size) {
return ApiResponse.success(PageVO.of(bookService.list(page,size)));
}對比表格:
| 緯度 | 非 RESTful | RESTful |
| URL | /getBook.php?page=1&size=20 | /book?page=1&size=20 |
| HTTP | GET | GET |
| 返回 | List<Book> | ApiResponse<PageVO<Book>> |
| 狀態(tài)碼 | 200(包一切) | 200(正常) |
| 示例返回 | [{...}, {...}] | {code:200,data:{records:[...],total:90}} |
3.2 新增圖書
非 RESTful 代碼:
@PostMapping("/addBook")
public Book addBook(@RequestBody Book book) {
return bookService.create(book); // 直接實(shí)體
}RESTful 代碼:
@PostMapping("/book")
@ResponseStatus(HttpStatus.CREATED)
public ApiResponse<Book> create(@Valid @RequestBody Book book) {
return ApiResponse.success(bookService.create(book));
}對比表格:
| 緯度 | 非 RESTful | RESTful |
| URL | /addBook.php | /book |
| HTTP | POST | POST |
| 返回 | Book | ApiResponse<Book> |
| 狀態(tài)碼 | 200(包一切) | 201(Created) |
| 示例返回 | {...} | {code:200,data:{}} |
3.3 修改圖書
非 RESTful 代碼:
@PostMapping("/updateBook")
public Book update(@Valid @RequestBody Book book) {
//處理修改邏輯
return book;
}
RESTful 代碼:
@PutMapping("/book")
public ApiResponse<Book> update(@Valid @RequestBody Book book) {
//處理修改邏輯
return ApiResponse.success(book);
}對比表格:
| 緯度 | 非 RESTful | RESTful |
| URL | /updateBook.php | /book |
| HTTP | POST | PUT |
| 返回 | Book | ApiResponse<Book> |
| 示例返回 | {...} | {code:200,data:{}} |
3.4 刪除圖書
非 RESTful 代碼:
@GetMapping("/deleteBook")
public String deleteBook(@RequestParam Long id) {
bookService.delete(id);
return "刪除成功"; // 字符串
}RESTful 代碼:
@DeleteMapping("/book/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ApiResponse<String> delete(@PathVariable Long id) {
bookService.deleteById(id);
return ApiResponse.success("刪除成功");
}對比表格:
| 緯度 | 非 RESTful | RESTful |
| URL | /deleteBook.php?id=1 | /book/1 |
| HTTP | GET(?) | DELETE |
| 返回 | String("刪除成功") | ApiResponse<String> |
從上述可以看出,使用restful風(fēng)格,增刪查改接口的url可以命名相同/book,因?yàn)槭歉鶕?jù)不同的方式(GET、POST、PUT、DELETE)來區(qū)分的。
四、SpringBoot 實(shí)戰(zhàn)
4.1 前提準(zhǔn)備實(shí)體類
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Long id;
private String name;
private BigDecimal price;
}4.2 restful返回規(guī)范
@Data
public class ApiResponse<T> {
private int code;
private String message;
private T data;
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> resp = new ApiResponse<>();
resp.code = 200;
resp.message = "success";
resp.data = data;
return resp;
}
}4.3 Controller類(RESTful 核心)
@RestController
@RequestMapping("/books")
@Validated
public class BookController {
private final Map<Long, Book> repo = new ConcurrentHashMap<>();
// 查詢集合
@GetMapping
public ApiResponse<List<Book>> list(@RequestParam(required = false) String name) {
List<Book> list = repo.values().stream()
.filter(b -> name == null || b.getName().contains(name))
.collect(Collectors.toList());
return ApiResponse.success(list);
}
// 查詢單個(gè)
@GetMapping("/{id}")
public ApiResponse<Book> get(@PathVariable Long id) {
Book book = Optional.ofNullable(repo.get(id))
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
return ApiResponse.success(book );
}
// 新增
@PostMapping
public ApiResponse<Book>create(@Valid @RequestBody Book book) {
book.setId(System.currentTimeMillis());
repo.put(book.getId(), book);
return ApiResponse.success(list);
}
// 全量更新
@PutMapping("/{id}")
public ApiResponse<Book> update(@PathVariable Long id, @Valid @RequestBody Book book) {
//自定義更新邏輯
return ApiResponse.success(list);
}
// 刪除
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ApiResponse<?> delete(@PathVariable Long id) {
return ApiResponse.success(repo.remove(id));
}
}4.4 請求示例
GET /books → 查詢圖書列表
GET /books/1 → 查詢 id=1 的圖書
POST /books → 新增圖書
PUT /books/1 → 全量更新 id=1 的圖書
DELETE /books/1 → 刪除 id=1 的圖書
以上就是基于SpringBoot打造RESTful API實(shí)戰(zhàn)指南的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot打造RESTful API的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JAVA實(shí)現(xiàn)經(jīng)典掃雷游戲的示例代碼
windows自帶的游戲《掃雷》是陪伴了無數(shù)人的經(jīng)典游戲,本程序參考《掃雷》的規(guī)則進(jìn)行了簡化,用java語言實(shí)現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理。感興趣的可以學(xué)習(xí)一下2022-01-01
Mybatis的parameterType造成線程阻塞問題分析
這篇文章主要詳細(xì)分析了Mybatis的parameterType造成線程阻塞問題,文中有詳細(xì)的解決方法,及相關(guān)的代碼示例,具有一定的參考價(jià)值,感興趣的朋友可以借鑒閱讀2023-06-06
SpringBoot項(xiàng)目中org.junit.jupiter.api.Test報(bào)錯(cuò)問題及解決
這篇文章主要介紹了SpringBoot項(xiàng)目中org.junit.jupiter.api.Test報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Spring?Boot?+?Mybatis?Plus實(shí)現(xiàn)樹狀菜單的方法
這篇文章主要介紹了Spring?Boot?+?Mybatis?Plus實(shí)現(xiàn)樹狀菜單,包括實(shí)體類中添加子菜單列表和集合及構(gòu)建菜單樹的詳細(xì)代碼,代碼簡單易懂,需要的朋友可以參考下2021-12-12
mybatis 忽略實(shí)體對象的某個(gè)屬性(2種方式)
這篇文章主要介紹了mybatis 忽略實(shí)體對象的某個(gè)屬性方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Spring反射內(nèi)置工具類ReflectionUtils用法及說明
這段文章主要介紹了Java反射機(jī)制及其在獲取sentinel熔斷規(guī)則map和操作類屬性方法中的應(yīng)用,通過JDK和Spring的ReflectionUtils展示了如何優(yōu)雅地處理反射操作,提升代碼的可閱讀性和維護(hù)性2026-06-06

