从零到一:用 SpringBoot 打造 RESTful API 实战指南

目录

[一、什么是 RESTful API?](#一、什么是 RESTful API?)

二、设计规范

[2.1 controller接口设计规范](#2.1 controller接口设计规范)

[2.2 返回结构设计规范](#2.2 返回结构设计规范)

三、restful与非restful风格对比

3.1查询图书

[3.2 新增图书](#3.2 新增图书)

[3.3 修改图书](#3.3 修改图书)

[3.4 删除图书](#3.4 删除图书)

[四、SpringBoot 实战](#四、SpringBoot 实战)

[4.1 前提准备实体类](#4.1 前提准备实体类)

[4.2 restful返回规范](#4.2 restful返回规范)

[4.3 Controller类(RESTful 核心)](#4.3 Controller类(RESTful 核心))

[4.4 请求示例](#4.4 请求示例)


一、什么是 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 代码:

java 复制代码
@GetMapping("/getBook")
public List<Book> getBooks(@RequestParam int page,@RequestParam int size) {
    return bookService.list(page,size);   // 直接 List
}

RESTful 代码:

java 复制代码
@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 代码:

java 复制代码
@PostMapping("/addBook")
public Book addBook(@RequestBody Book book) {
    return bookService.create(book);   // 直接实体
}

RESTful 代码:

java 复制代码
@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 代码:

java 复制代码
    @PostMapping("/updateBook")
    public Book update(@Valid @RequestBody Book book) {
           //处理修改逻辑
        return book;
    }

RESTful 代码:

java 复制代码
    @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 代码:

java 复制代码
@GetMapping("/deleteBook")
public String deleteBook(@RequestParam Long id) {
    bookService.delete(id);
    return "删除成功";   // 字符串
}

RESTful 代码:

java 复制代码
@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 前提准备实体类

java 复制代码
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Book {
    private Long id;
    private String name;
    private BigDecimal price;
}

4.2 restful返回规范

java 复制代码
@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 核心)

java 复制代码
@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 的图书

暂时分享到这里啦,点赞 + 收藏 + fork ,一起 RESTful

如果有任何疑问欢迎在评论区留言,谢谢。

相关推荐
无风听海2 分钟前
Claude Agent Skills 的四种设计模式;从渐进式披露到最小权限
java·算法·设计模式
豆瓣鸡31 分钟前
Guava RateLimiter 限流实战:从令牌桶原理到 Nacos 动态配置
spring boot·微服务·nacos·guava
geovindu35 分钟前
java: Facade Pattern
java·开发语言·后端·外观模式·结构型模式
listening77737 分钟前
HarmonyOS 6.1 元服务深度优化:从“秒开”到“常驻”的极致体验
java·开发语言·spring
布朗克16839 分钟前
Go 入门到精通-29-测试与基准
开发语言·后端·golang·测试与基准
你驴我1 小时前
WhatsApp Cloud API 速率限制下的令牌桶与退避策略实践
网络·后端·python
AC赳赳老秦1 小时前
司法公开数据采集应用:OpenClaw 抓取裁判文书公开信息,批量整理同类参考案例
java·大数据·python·数据挖掘·数据分析·php·openclaw
笑小枫1 小时前
用 Claude Code 推翻重写笑小枫网站
java·人工智能·spring boot·ai编程
ClouGence1 小时前
SAP HANA 到 Doris 数据迁移:4 种方案对比与迁移教程
数据库·后端·dba
霸道流氓气质1 小时前
ApiPost 中配置自动获取 Token 并调用业务接口完整指南
java·服务器·数据库