【PHP】RestFul简介和使用
1.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(更新部分字段)
1.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 返回红色的cars GET /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: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; 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更加标准
1.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); } }
1.4 具体分析和测试
因为测试时要用到Postman软件,官网下载又极慢,所以这里提供了百度网盘的链接:
链接:Postman安装包
提取码:dnbf
1.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就是路径中的数据
过滤、排序、分页、选择字段时用 ? 号传参
1.4.1 查询某个用户信息
1.4.2 查询用户列表
1.4.3 添加用户
日志中的数据
1.4.4 测试更新
日志中的内容
1.4.5 测试删除
1.5 User与Pet之间的关联关系
User可以有多个Pet,但是一个Pet只能属于一个User
猜你喜欢
- 【PHP】PHP开发中如何使用Nginx实现负载均衡
- 在现代web应用开发中,高并发访问是一个必须要面对的挑战。负载均衡是解决这个问题的一种有效的方案。在php开发中,使用nginx实现负载均衡是一个非常常见的方法。本文将详细介绍如何在php开发中使用nginx实现负载均衡。一、Nginx及负载均衡的基本概念NginxNginx是一款轻量级的高性能的web服务器和反向代理服务器。它的出现解决了Apache这样的传统web服务器在高并发访问下的性能瓶颈。Nginx具有极高的性能、稳定性和安全性,并且支持大量的并发连接。负载均衡负载均衡是一种将网络流量
- 【PHP】php中的compact()的用法
- compact()参数有两种变量名的字符串形式数组的变量名变量名的字符串$city = "San Francisco"; $state = "CA"; $event = "SIGGRAPH"; $location=["city",'state']; $result=compact('city','
- 【PHP】php8的扩展arginfo生成工具之使用初体验
- hp8提供了非常方便的扩展函数或类参数信息的生成工具。只需要维护一份xyz.stub.php,就可以使用工具生成 xyz_arginfo.h。毫无疑问,这种方式,又降低了广大 phper 开发扩展的门槛,更易维护。上手体验:生成扩展骨架。cd ext php ext_skel.php --ext test随便添加一个函数,更改 test.stub.php。<?php /** @generate-function-entrie
- 【PHP】微信JSAPI支付V3版本
- article class="baidu_pl"><div id="article_content" class="article_content clearfix"><link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css"/><link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-044f2cf1dc.css"/></div></article><!--autointro--
- 【PHP】PHP 8.3 重磅发布:创新与增强,开创未来
- PHP 8.3 于 2023 年 11 月 23 日发布,标志着该语言的发展又迈出了重要的一步。该版本引入了许多新功能、性能改进和弃用,旨在增强 PHP 开发体验。在这份综合指南中,我们将深入探讨这些更新,提供见解、技巧和创造性的代码示例,以帮助您适应并充分利用 PHP 8.3。只读类的增强PHP 8.3 对只读类的克隆行为进行了修改,允许在克隆期间重新初始化只读属性。这一更改解决了深度克隆中的特定边缘情况。参考以下示例:12345678910class Article {
- 【PHP】tp使用lunar-php,获取节日节气
- lunar-php 是一个用于获取公历和农历(即阳历和阴历)信息的 PHP 库。要使用 lunar-php 获取节日和节气,你需要先安装这个库。 首先,通过 Composer 安装 lunar-php:composer require chenmingl/lunar-php获取阳历阴历节日及节气:require 'vendor/autoload.php'; use Lunar\Lunar; //&nbs
- 【PHP】用PHP从数据库到后端到前端完整实现一个中秋节祝福语项目
- 文章目录🚀一、前言🚀二、开发环境准备🚀三、功能实现🍁3.3.1 HTML布局🍁3.3.2 JQuery事件处理🍁3.2.1 连接数据库🍁3.2.1 获取祝福语🍁3.2.3 处理请求🍁3.2.4 配置Nginx与FPM🍁3.1.1 创建数据库及表结构🍁3.1.2 准备数据🔎3.1 准备数据库和数据🔎3.2 后端开发🔎3.3 前端开发🚀四、运行和测试🔎4.1 绑定host🔎4.2 开始测试🚀五、总结中秋佳节即将来临!在这特殊的时刻,我们特别举办一场属于程序员的中秋