基于SpringBoot打造RESTful API实战指南
作者:中文很快乐
本文详细介绍了RESTful API的基本概念、设计规范以及与非RESTful风格的对比,通过Spring Boot实战部分,展示了如何实现一个简单的RESTful API,需要的朋友可以参考下
一、什么是 RESTful API?
REST(Representational State Transfer)是一种 面向资源 的架构风格,核心思想:
用 URL 定位资源,用 HTTP 动词描述操作
面向资源怎么理解呢?:
RESTful API 就是符合 REST 约束的接口,特点:
- ✅ 无状态(每次请求自带上下文)
- ✅ 统一接口(GET/POST/PUT/DELETE)
- ✅ 资源导向(URL 是名词,不是动词)
二、设计规范
2.1 controller接口设计规范
RESTful API的RequestMapping的方式有4种,以图书为例,每一种的应用场景如下:
| 动作 | 资源集合 /books | 单个资源 /books/{id} |
| GET | 查询集合 | 查询单个 |
| POST | 新增集合 | ❌ |
| PUT | 批量更新 | 更新单个 |
| DELETE | 批量删除 | 删除单个 |
2.2 返回结构设计规范
| 字段 | 类型 | 说明 |
| code | int | HTTP 状态码(200/400/404/500) |
| message | string | 用户可读提示信息 |
| data | 泛型T | 业务数据(含分页) |
三、restful与非restful风格对比
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>> |
| 状态码 | 200(包一切) | 200(正常) |
| 示例返回 | [{...}, {...}] | {code:200,data:{records:[...],total:90}} |
3.2 新增图书
非 RESTful 代码:
@PostMapping("/addBook")
public Book addBook(@RequestBody Book book) {
return bookService.create(book); // 直接实体
}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> |
| 状态码 | 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风格,增删查改接口的url可以命名相同/book,因为是根据不同的方式(GET、POST、PUT、DELETE)来区分的。
四、SpringBoot 实战
4.1 前提准备实体类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Long id;
private String name;
private BigDecimal price;
}4.2 restful返回规范
@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);
}
// 查询单个
@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实战指南的详细内容,更多关于SpringBoot打造RESTful API的资料请关注脚本之家其它相关文章!
