RESTful风格请求方式详解与示例​

为了方便大家更好的理解Restful风格的api请求方式,我将以最简单的图书管理系统来举例​​,逐一举证说明每种请求方式的实际用法​​,包含URI设计、请求示例和注意事项。
我们常用的Restful风格的api主要有五种,分别是GET、POST、PUT、PATCH、DELETE

一、环境准备

1、引入依赖

在pom.xml文件中引入以下依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、实体类和模拟数据
// 图书实体类
public class Book {
    private Long id;
    private String title;
    private String author;
    private Integer stock;

    // 构造方法、Getter/Setter 省略(可用Lombok @Data简化)
}

// 模拟内存数据库
@Service
public class BookService {
    private final Map<Long, Book> books = new HashMap<>();
    private Long nextId = 1L;

    // 初始化测试数据
    public BookService() {
        saveBook(new Book(null, "Java编程思想", "Bruce Eckel", 5));
        saveBook(new Book(null, "Python数据分析", "Wes McKinney", 3));
    }

    // 保存图书(自动生成ID)
    public Book saveBook(Book book) {
        book.setId(nextId);
        books.put(nextId, book);
        nextId++;
        return book;
    }

    // 其他方法(findById, findAll, update, delete)见下文控制器代码
}

二、具体接口类(Controller)

@RestController
@RequestMapping("/api/books")
public class BookController {
    @Autowired
    private BookService bookService;

    // --- GET: 查询所有图书 ---
    @GetMapping
    public ResponseEntity<List<Book>> getAllBooks() {
        List<Book> bookList = new ArrayList<>(bookService.findAll());
        return ResponseEntity.ok(bookList);
    }

    // --- GET: 根据ID查询图书 ---
    @GetMapping("/{id}")
    public ResponseEntity<Book> getBookById(@PathVariable Long id) {
        Book book = bookService.findById(id);
        if (book == null) {
            return ResponseEntity.notFound().build(); // 404
        }
        return ResponseEntity.ok(book); // 200
    }

    // --- POST: 新增图书 ---
    @PostMapping
    public ResponseEntity<Book> createBook(@RequestBody Book book) {
        Book savedBook = bookService.saveBook(book);
        URI location = ServletUriComponentsBuilder
                .fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedBook.getId())
                .toUri();
        return ResponseEntity.created(location).body(savedBook); // 201
    }

    // --- PUT: 全量更新图书 ---
    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBook(
            @PathVariable Long id, 
            @RequestBody Book bookDetails) {
        Book existingBook = bookService.findById(id);
        if (existingBook == null) {
            return ResponseEntity.notFound().build(); // 404
        }
        // 全量覆盖字段
        existingBook.setTitle(bookDetails.getTitle());
        existingBook.setAuthor(bookDetails.getAuthor());
        existingBook.setStock(bookDetails.getStock());
        bookService.update(existingBook);
        return ResponseEntity.ok(existingBook); // 200
    }

    // --- PATCH: 局部更新库存 ---
    @PatchMapping("/{id}/stock")
    public ResponseEntity<Book> updateStock(
            @PathVariable Long id, 
            @RequestBody Map<String, Integer> updates) {
        Book existingBook = bookService.findById(id);
        if (existingBook == null) {
            return ResponseEntity.notFound().build(); // 404
        }
        // 仅更新stock字段
        Integer newStock = updates.get("stock");
        if (newStock != null) {
            existingBook.setStock(newStock);
            bookService.update(existingBook);
        }
        return ResponseEntity.ok(existingBook); // 200
    }

    // --- DELETE: 删除图书 ---
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
        if (bookService.findById(id) == null) {
            return ResponseEntity.notFound().build(); // 404
        }
        bookService.delete(id);
        return ResponseEntity.noContent().build(); // 204
    }
}

三、接口介绍

1、GET:获取资源​(获取全部数据)

对应注解:@GetMapping
可以看到,此处的注解并没有像其他接口那样,后面跟上参数,那么说明这是一个不需要传任何参数就可以直接调用的接口。直接返回所有数据,同时,如果加上参数,那么就可以实现条件查询(根据id或其他数据查询)。

URI​​: GET /api/books
响应​​:

[
  { "id": 1, "title": "Java编程思想", "stock": 5 },
  { "id": 2, "title": "Python数据分析", "stock": 3 }
]

状态码​​: 200 OK

2、GET:获取资源(获取单本书籍详情​)

对应注解:@GetMapping(“/{id}”)
根据条件查询,就在注解后面加上(“/{id}”),表示根据id查询,如果要根据名字查询,就可以写成(“/{name}”)。同时,需要在方法的参数前面加上@PathVariable注解,表示是由请求路径传递过来的参数。

URI​​: GET /api/books/1
​​响应​​:

{ 
  "id": 1, 
  "title": "Java编程思想", 
  "author": "Bruce Eckel", 
  "stock": 5 
}

状态码​​: 200 OK
注意​​:若书籍不存在(如GET /api/books/999),应返回null

3、POST:创建资源​(新增一本书籍)

对应注解:@PostMapping,可以看到,PostMapping也是不需要带参数的,这些注解如果携带参数,一般是在请求地址中“我们可以看到”的参数。那么有同学就要问了,没有携带参数我们怎么新增数据呢。那是因为还有另一种携带参数的方法,那就是请求体。
public ResponseEntity createBook(@RequestBody Book book)
可以看到,在Book参数前面我们加上了@RequestBody,代表这就是通过请求体形式传递过来的参数。
URI​​: POST /api/books
​​请求体​​:

{ 
  "title": "深入理解计算机系统", 
  "author": "Randal E.Bryant", 
  "stock": 10 
}

成功响应​​:

{ 
  "id": 3,  // 系统自动生成ID
  "title": "深入理解计算机系统", 
  "author": "Randal E.Bryant", 
  "stock": 10 
}

状态码​​: 201 Created
​​Header​​: Location: /api/books/3(指向新资源的URI)
​​常见错误​​:若未传必填字段(如title),应返回400 Bad Request。

4、PUT:全量更新资源​(更新书籍信息)

请求路径参数用于指向需要修改的数据,请求体为更新后的数据
URI​​: PUT /api/books/1
请求体​​:

{ 
  "title": "Java编程思想(第5版)", 
  "author": "Bruce Eckel", 
  "stock": 8 
}

响应​​:返回更新后的完整数据(字段必须全量提交)。
​​状态码​​: 200 OK
​​风险案例​​:
若仅提交部分字段(如只传title),其他字段可能被覆盖为空值!
👉 ​​错误用法​​:

// 请求体
{ "title": "新书名" }  // 缺少author和stock字段

此时,author和stock会被置为null。若需局部更新,应改用​​PATCH​​。

5、PATCH:局部更新资源​

场景:调整书籍库存​​
​​URI​​: PATCH /api/books/1
​​请求体​​:

{ 
  "stock": 3  // 只修改库存字段
}

响应​​:返回更新后的完整数据(仅stock变化,其他字段保留原值)。
​​状态码​​: 200 OK
​​对比PUT​​:PUT需提交完整数据,PATCH只需传需修改的字段。

6、DELETE:删除资源​​

​​场景:下架一本书籍​​
​​URI​​: DELETE /api/books/1
​​响应​​: 无内容(表示删除成功)。

四、总结:图书管理API速查表​

HTTP方法对照表

方法场景示例URI幂等性安全性
GET查书单/查详情/api/books/1
POST新增书籍/api/books
PUT全量更新书籍信息/api/books/1
PATCH调整库存/局部更新/api/books/1
DELETE下架书籍/api/books/1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

igxia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值