> 文档中心 > RestFul简介和使用

RestFul简介和使用


2. RestFul简介和使用

2.1 RestFul简介

REST全称是(Resource) Representational State Transfer,翻译过来为“资源代表状态转移”,中文意思是表述性状态转移。它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一。 他在论文中提到:“我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件原则不是标准不是规范。” 如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。

RestFul: 是一种以网络为基础构架一种架构风格 一个架构符合Rest设计原则和约束称这个架构为RestFul

Rest 词: 并没有 更新技术 组件 服务 让我们web请求能够利用web中标准 和 能力 更好描述架构

REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。 所以我们这里描述的REST也是通过HTTP实现的REST。

总结

Restful 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

web开发: 实现所有功能

restful: 软件设计风格 标准 简洁 层次 优雅

符合rest设计原则和约束的架构称之为restFul

URL定义

  • 资源:互联网所有的事物都可以被抽象为资源
    • 一首歌 一张图片 数据库一条记录
  • 资源操作:使用POST(添加)、DELETE(删除)、PUT(修改)、GET(查询),使用不同请求方法对资源进行操作。
    • 删除 delete
    • 查询 get
    • 添加 post
    • 修改 put (修改全部字段)| patch(更新部分字段)

2.2 传统方式与RESTful操作资源对比

传统方式操作资源

  • http://127.0.0.1/item/queryUser.action?id=1 查询,GET

  • http://127.0.0.1/item/saveUser.action 新增,POST

  • http://127.0.0.1/item/updateUser.action 更新,PUT

  • http://127.0.0.1/item/deleteUser.action?id=1 删除,DELETE

    注意:传统的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了queryUser,新增的时候用了saveUser ,修改的时候用了updateUser,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,PUT就是修改,delete就是删除,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.

使用RESTful操作资源

  • 【GET】 /users # 查询用户信息列表

  • 【GET】 /users/1001 # 查看某个用户信息

  • 【POST】 /users # 新建用户信息

  • 【PUT】 /users/1001 # 更新用户信息(全部字段)

  • 【PATCH】 /users/1001 # 更新用户信息(部分字段)

  • 【DELETE】 /users/1001 # 删除用户信息

Rest API设计风格原则

# 1.使用名词而不是动词- 不要使用:如:    /getAllUsers    get   /users  get /users/002    /createNewUser  post  /users    /deleteAllUser  delete /users/001# 2.Get方法和查询参数不应该涉及状态改变- 使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变# 3.使用复数名词- 不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。如:    /cars 而不是 /car    /users 而不是 /user    /products 而不是 /product    /settings 而不是 /setting    /orders   而不是 /order# 4. 使用子资源表达关系- 如果一个资源与另外一个资源有关系,使用子资源:如:    GET /cars/711/drivers/ 返回 car 711的所有司机    GET /cars/711/drivers/4 返回 car 711的4号司机    GET /users/11/pets      返回 user 11的所有宠物    GET /users/11/pets/2    返回 user 11的2号宠物# 5.使用Http头声明序列化格式- 在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定对于controller:Accept 定义接受的类型Content-Type 定义响应类型# 6.为集合提供过滤 排序 选择和分页等功能- Filtering过滤:使用唯一的查询参数进行GET /cars?color=red 返回红色的carsGET /cars?seats<=2 返回小于两座位的cars集合- Sorting排序:允许针对多个字段排序GET /cars?sort=-manufactorer,+model这是返回根据生产者降序和模型升序排列的car集合- Field selection移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。GET /cars?fields=manufacturer,model,id,color- Paging分页使用 limit 和offset.实现分页,缺省limit=20 和offset=0;GET /cars?offset=10&limit=5为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.链接到下一页或上一页可以在HTTP头的link规定,遵循Link规定:Link: ; rel="next",; rel="last",; rel="first",; rel="prev",# 7.版本化你的API  支付宝  v1  v2   v3- 使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.一般在Url后面使用?v/blog/api/v1# 8. 使用Http状态码处理错误- 如果你的API没有错误处理是很难的,只是返回500和出错堆栈不一定有用- Http状态码提供70个出错,我们只要使用10个左右: `200 – OK – 一切正常  `201 – OK – 新的资源已经成功创建  `204 – OK – 资源已经成功删除  `304 – Not Modified – 客户端使用缓存数据  `400 – Bad Request – 请求无效,需要附加细节解释如 "JSON无效"  `401 – Unauthorized – 请求需要用户验证  `403 – Forbidden – 服务器已经理解了请求,但是拒绝服务或这种请求的访问是不允许的。  `404 – Not found – 没有发现该资源  `422 – Unprocessable Entity – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。  `500 – Internal Server Error – API开发者应该避免这种错误。使用详细的错误包装错误:  状态码  错误信息      正确:状态码  +  数据  复杂的话还有header头信息{  "errors": [   {    "userMessage": "Sorry, the requested resource does not exist",// 错误信息    "internalMessage": "No car found in the database",    "code": 34,// 状态码    "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"// 错误链接   }  ]}

传统方式操作资源会在控制器方法上使用@RequestMapping注解来接收添加、删除、更新、查询的请求,

RestFul方式操作资源会在方法上使用@PostMapping注解专门来接收添加请求

​ 使用@DeleteMapping注解专门来接收删除请求

​ 使用@PutMapping注解专门来接收更新请求(全部字段)|@PatchMapping(部分字段)

​ 使用@GetMapping注解专门来接收查询请求

这样的话对于每一种方法都有唯一类型的请求,而不是使用@RequestMapping注解可以接受所有类型的请求,RestFul更加标准

2.3 使用RestFul方式开发Controller

用到的包结构

在这里插入图片描述

用到的资源类

User

public class User {    private Integer id;    private String name;    private Double salary;    private Date bir;  // 以免影响阅读体验构造方法、get、set方法没有粘,但是是有的}

Pet

public class Pet {    private Integer id;    private String name;    private Integer age;// 以免影响阅读体验构造方法、get、set方法没有粘,但是是有的}

开发Controller

UserController

//@RestController  // @RestController: 专用于restful风格的注解 = @Controller (控制器) + @ResponseBody (方法返回值为json)@RestController@RequestMapping("/v1/users")public class UserController {    private static final Logger log = LoggerFactory.getLogger(UserController.class);    // ResponseEntity:springmvc封装的专用于restful的响应类 这个类在响应时可以提供响应的状态码,同时还可以自定义响应头信息    // HttpStatus:  springmvc封装的一个枚举类  这个类中都是网络中状态码    /**     * 查询某个用户详细     * @param id     * @return     */    @GetMapping("/{id}")   // 也可以写成@RequestMapping(value = "/{id}", method = RequestMethod.GET)    // @GetMapping是@RequestMapping的子类注解,使用@GetMapping代表只能使用GET方式访问到当前请求    // @GetMapping的参数这里不能写死,日后需要传一个参数,所以写一个占位id    // @PathVariable注解:代表在路径中获取请求参数  (不获取form表单了也不获取问号后面的了)    // @PathVariable注解的value属性写获取路径中的哪个参数,获取上面@GetMapping("/{id}")中的id    // Integer id  接收路径中的参数    //@ResponseBody   // 将控制器方法返回值转为json    public ResponseEntity<User> user(@PathVariable("id")  Integer id){ log.info("本次id: {}", id); User user = new User(id, "小陈", 2300.23, new Date()); return new ResponseEntity<>(user, HttpStatus.OK); // 第一个参数是body是什么 // 第二个参数是状态码是什么  HttpStatus.OK :代表返回成功    }    /**     * 用户列表     * @return     */    @GetMapping    //@ResponseBody    public ResponseEntity<List<User>> users(){ List<User> users = new ArrayList<>(); users.add(new User(21, "小王", 2300.23, new Date())); users.add(new User(24, "小金豆", 3400.23, new Date())); return new ResponseEntity<>(users, HttpStatus.OK);    }    /**     * 添加用户     * @param user     */    @PostMapping    //@ResponseBody    // @ResponseBody 将方法返回值转为json格式数据 并响应请求    // @RequestBody: 接收请求的json格式数据 将json格式数据转化为对象    public ResponseEntity<Void> save(@RequestBody User user){   // 只接受json log.info("name:{}, salary:{}, bir:{}", user.getName(), user.getSalary(), user.getBir()); // 调用业务方法 return new ResponseEntity<>(HttpStatus.NO_CONTENT); // 查询成功返回状态码为 HttpStatus.NO_CONTENT : 没有内容    }    /**     * 更新用户     * @param user     */    @PutMapping("/{id}")  // 全字段更新    //@ResponseBody    // @PathVariable 从路径中获取    // @RequestBody 从响应体获取    public ResponseEntity<Void> update(@PathVariable("id") Integer id, @RequestBody User user){ log.debug("id: {}", id); log.info("name:{}, salary:{}, bir:{}", user.getName(), user.getSalary(), user.getBir()); // 调用业务方法 return new ResponseEntity<>(HttpStatus.NO_CONTENT); // 更新成功返回状态码为 HttpStatus.NO_CONTENT : 没有内容    }    /**     * 删除用户     * @param id     */    @DeleteMapping("/{id}")    //@ResponseBody    public ResponseEntity<Void> delete(@PathVariable("id") Integer id){ log.info("本次id: {}", id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); // 更新成功返回状态码为 HttpStatus.NO_CONTENT : 没有内容    }    /**     * 获取这个人的所有宠物     * @return     */    @GetMapping("/{id}/pets")    public ResponseEntity<List<Pet>> pets(@PathVariable("id") Integer id){ log.info("查询哪个人id: {}", id); List<Pet> pets = Arrays.asList(new Pet(21, "小红帽", 23), new Pet(22, "小猪", 22)); return new ResponseEntity<>(pets, HttpStatus.OK);    }    /**     * 获取这个人的某个宠物     * @return     */    @GetMapping("/{id}/pets/{pid}")    public ResponseEntity<Pet> pet(@PathVariable("id") Integer id, @PathVariable("pid") Integer petId){ log.info("查询哪个人id: {}", id); Pet pet = new Pet(21, "小红帽", 23); return new ResponseEntity<>(pet, HttpStatus.OK);    }}

2.4 具体分析和测试

因为测试时要用到Postman软件,官网下载又极慢,所以这里提供了百度网盘的链接:

链接:Postman安装包
提取码:dnbf

2.4.0 前提了解

在这里插入图片描述


在这里插入图片描述


用到的注解:

  • @GetMapping:方法加上这个注解之后方法只能接受GET请求

  • @PostMapping:方法加上这个注解之后方法只能接受POST请求

  • @PutMapping:方法加上这个注解之后方法只能接受PUT请求

  • @DeleteMapping:方法加上这个注解之后方法只能接受DELETE请求

  • @PathVariable:在方法前参数前加上这个用来获取路径中数据给参数

  • @RequestBody:在方法前加上这个数据代表这个数据从路径中接受的话只能接受json形式的数据

  • @ResponseBody:将控制器方法的返回值转化为json

用到的类:

ResponseEntity:springmvc封装的专用于restful的响应类 这个类在响应时可以提供响应的状态码,同时还可以自定义响应头信息

HttpStatus: springmvc封装的一个枚举类 这个类中都是网络中状态码

注:

路径中获取数据不等于在url中以问号拼接数据,而是

http://localhost:8080/v1/users/100 后面的100就是路径中的数据

过滤、排序、分页、选择字段时用 ? 号传参

2.4.1 查询某个用户信息

在这里插入图片描述

在这里插入图片描述

2.4.2 查询用户列表

在这里插入图片描述

在这里插入图片描述

2.4.3 添加用户

在这里插入图片描述

在这里插入图片描述

日志中的数据

在这里插入图片描述

2.4.4 测试更新

在这里插入图片描述

在这里插入图片描述

日志中的内容

在这里插入图片描述

2.4.5 测试删除

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.5 User与Pet之间的关联关系

User可以有多个Pet,但是一个Pet只能属于一个User

在这里插入图片描述

在这里插入图片描述