第十六章、RestFul API
-
什么是REST
REST 全称是 Resource Representational State Transfer,中文意思是表述性状态转移,它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一。他在论文中表示:我这篇文章的目的就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条条件和原则,“如果一个架构复合REST的约束条件和原则,我们就称它为RESTful架构”
RestFul:是一种以网络为基础构架一种架构一种架构风格,一个符合Rest设计原则和约束成这个架构为RestFul。
REST本身并没有创造新的技术、组件和服务、而隐藏在RESTful背后的理念就是使用web的现有特征和能力,更好地使用现有web标准中的一些准则和约束。
-
RestFul遵循的架构约束
- 客户端-服务器架构:由客户端、服务器和资源组成,通过HTTP管理请求。
- 无状态的客户端-服务器通信:每个请求都是独立的,不会在请求之间保存客户端信息。
- 可缓存的数据:通过缓存数据来优化客户端-服务器交互。
- 统一的接口:信息以标准形式传输,包括资源的标识和表示之间的分离,以及自描述的消息返回给客户端。
-
总结
RestFul是一种架构风格,不是标准,只是提供了一组设计原则和约束条件,它主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁、更有层次,更易于实现缓存等机制。
-
URL定义
- 资源:互联网所有的事务都可以称为资源:一张图片、一段文本、一条记录…..
- 资源操作:使用POST添加、DELETE删除,PUT修改,GET查询,使用不同请求方法对资源进行操作
- 删除 delete
- 查询 get
- 添加 post
- 修改 put(修改全部字段) patch(更新部分字段)
-
传统方式操作资源
- http://127.0.0.1/item/queryUser.action?id=1 查询 GET
- http://127.0.0.1/item/saveUser 新增 POST
- http://127.0.0.1/item/updateUser.action 更新 PUT
- http://127.0.0.1/item/deleteUser.action?id=1 删除 DELETE
注意:传统的操作是没有问题的,大神认为有问题的:你每次请求的接口或者地址都是在做描述,其实完全没有这个必要,我使用了get请求,就是代表查询,使用post就是代表新增请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful。
-
使用RESTful操作资源
- 【GET】 /users 查询用户信息列表
- 【GET】 /users/1001 查看某个用户信息
- 【POST】 /users 新增用户信息
- 【PUT】 /users/1001 更新用户信息(全部字段)
- 【PATCH】 /users/1001 更新用户信息(部分字段)
- 【DELETE】 /users/1001 删除用户信息
第一个RestFul风格的API
@RestController // 专用于restful风格的注解,只能返回json/Xml格式的数据
@RequestMapping("/v1/users")
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
/**
* 获取单个用户
* @param id
* @return
*/
@GetMapping("/{id}")
public User user(@PathVariable("id") Integer id) {
log.info("id:{}", id);
return new User(21, "小明", 2000.2, new Date());
}
/**
* 用户列表
* @return
*/
@GetMapping()
public List<User> users() {
ArrayList<User> users = new ArrayList<>();
users.add(new User(21, "小明", 2000.2, new Date()));
users.add(new User(16, "小红", 3000.2, new Date()));
return users;
}
/**
* 添加用户
* @param user
*/
@PostMapping
public void saveUser(@RequestBody User user) {
log.info("用户信息:{}", user);
//调用业务方法...
}
/**
* 修改用户
* @param user
*/
@PutMapping("/{id}")
public void update(@PathVariable("id") Integer id, @RequestBody User user) {
log.info("更新用户的id:{}",id);
log.info("修改信息:{}", user);
//调用业务方法...
}
/**
* 删除用户
* @param id
*/
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") Integer id) {
log.info("id:{}",id);
}
}
**@RestController
注解**
**@RestController**
注解则是用来创建 REST API 控制器的。在 REST API 中,通常需要返回 JSON 或 XML 格式的数据,而不是 HTML 视图。因此,@RestController
注解结合了 @Controller
和 @ResponseBody
注解的功能,可以方便地实现 REST API 的开发。
@RequestBody
注解
@RequestBody
注解将请求体中的 JSON 数据转换为 Java 对象。
**@PathVariable
注解**
这个注解用于处理RESTful API中的URL路径参数。例如**@GetMapping("/{id}")
** ,我们需要使用@PathVariable
注解来提取URI中的{id},并将其作为方法的参数。
@PathVariable
还有一些属性可以使用:
-
指定路径变量的名称: 如果路径变量的名称与方法参数的名称不同,我们可以在
@PathVariable
注解中指定路径变量的名称。@GetMapping("/api/employees/{empId}") public String getEmployeeById(@PathVariable("empId") String id) { return "ID: " + id; }
-
指定默认值: 我们还可以在@PathVariable注解中指定默认值,以防路径变量未提供。
@GetMapping("/api/employees/{id}") public String getEmployeeById(@PathVariable(name = "id", required = false, defaultValue = "0") String id) { return "ID: " + id; }
-
如果业务逻辑还要往深一层查,比如查某个人的某个宠物,那么可以这样
/** * 获取某个人的所有宠物信息 */ @GetMapping("/{id}/pets") public List<Pet> pets(@PathVariable("id") Integer id) { log.info("查询人的id:{}", id); return Arrays.asList(new Pet(2, "旺财", 2),new Pet(3,"花花",1)); } /** * 获取某个人的某个宠物信息 */ @GetMapping("/{id}/pets/{pid}") public Pet pets(@PathVariable("id") Integer id,@PathVariable("pid") Integer pid) { log.info("查询人的id:{}", id); Pet pet = new Pet(2, "旺财", 2); return pet; }
ResponseEntity
和 HttpStatus
ResponseEntity
代表了整个 HTTP 响应,包括状态码、头部信息和响应体。可以完全配置 HTTP 响应。ResponseEntity
提供了泛型,所以我们可以使用它来代替API中的返回值
-
示例
//ResponseEntity springmvc中用于restful响应类,可以提供响应的状态码,以及自定义响应头信息 // HttpStatus:springmvc提供的枚举类型类 网络状态码 /** * 获取单个用户 */ @GetMapping("/{id}") public ResponseEntity<User> user(@PathVariable("id") Integer id) { log.info("id:{}", id); User user = new User(21, "小明", 2000.2, new Date()); return new ResponseEntity<>(user, HttpStatus.OK);// 状态码:200 } /** * 用户列表 */ @GetMapping() public ResponseEntity<List<User>> users() { ArrayList<User> users = new ArrayList<>(); users.add(new User(21, "小明", 2000.2, new Date())); users.add(new User(16, "小红", 3000.2, new Date())); return new ResponseEntity<>(users,HttpStatus.OK);// 状态码:200 } /** * 添加用户 */ @PostMapping public ResponseEntity<Void> saveUser(@RequestBody User user) { log.info("用户信息:{}", user); //调用业务方法... return new ResponseEntity<>(HttpStatus.NO_CONTENT);//没有内容,状态码204 }