您的当前位置:首页>全部文章>文章详情

【PHP】RestFul简介和使用

CrazyPanda发表于:2024-05-24 23:38:31浏览:229次TAG:

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

用到的包结构

1.png

用到的资源类

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 前提了解

在这里插入图片描述


1.png


用到的注解:

  • @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.png

1.png

1.4.2 查询用户列表

1.png

1.png

1.4.3 添加用户

1.png

1.png

日志中的数据

1.png

1.4.4 测试更新

1.png

1.png

日志中的内容

1.png

1.4.5 测试删除

1.png

1.png

1.png

1.5 User与Pet之间的关联关系

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

1.png

1.png

猜你喜欢

【PHP】ThinkPHP如何防止SQL注入攻击
在ThinkPHP中,参数绑定是一种安全的方式,用于处理用户输入,特别是在构建数据库查询时。参数绑定可以防止SQL注入攻击,因为绑定的参数会被自动转义,而不是直接插入到SQL语句中。以下是在ThinkPHP中使用参数绑定的一些建议。1. 控制器中的参数绑定:在控制器中,可以使用bind方法进行参数绑定。以下是一个简单的示例:public&nbsp;function&nbsp;index($id) { &nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;Db::
发表于:2024-01-04 浏览:336 TAG:
【PHP】tp使用lunar-php,获取节日节气
lunar-php 是一个用于获取公历和农历(即阳历和阴历)信息的 PHP 库。要使用 lunar-php 获取节日和节气,你需要先安装这个库。&nbsp;首先,通过 Composer 安装 lunar-php:composer&nbsp;require&nbsp;chenmingl/lunar-php获取阳历阴历节日及节气:require&nbsp;&#39;vendor/autoload.php&#39;; &nbsp; use&nbsp;Lunar\Lunar; &nbsp; //&amp;nbs
发表于:2024-04-09 浏览:318 TAG:
【PHP】interface接口、abstract抽象类、trait转载合并
1 .抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。 2 .抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。 3 .如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。
发表于:2025-03-21 浏览:48 TAG: #php
【PHP】如何使用PHP在微信小程序中实现AI功能?
如何使用PHP在微信小程序中实现AI功能?随着人工智能的发展,AI(Artificial Intelligence,人工智能)技术被广泛应用于各个领域。微信小程序作为一种强大的移动应用开发平台,也可以集成AI功能,为用户提供更智能的服务。本文将介绍如何使用PHP语言在微信小程序中实现AI功能,并且给出具体的代码示例。首先,我们需要了解微信小程序提供的开发接口和AI技术的实现方案。微信小程序提供了开放平台接口,可以通过接口与后端服务器进行交互。AI技术方面,我们可以选择使用开源的机器学习
发表于:2023-12-25 浏览:326 TAG:
【PHP】Yii框架的优点
Yii框架的优点主要包括高性能、易于扩展、易于使用、安全性好、易于安装、利用现代技术、高度可扩展性、鼓励测试、简化的安全方案、缩短开发时间、以及很容易通过调整获得更好的性能。高性能:Yii框架支持工作负载平衡和缓存,可以大幅提升Web应用程序的性能。易于扩展:Yii框架支持插件式架构,开发者可以很方便地添加或移除组件来满足不同的需求。易于使用:Yii框架具有操作简单、易于学习和易于使用的特点,可以大大节省开发人员的时间和精力。安全性好:Yii框架提供了严格的安全机制,使得Web应用程序更加安全可
发表于:2024-07-01 浏览:275 TAG:
【PHP】php数组合并有几种方法
php数组合并有四种方法。详细介绍:1、使用array_merge()函数,接受多个数组作为参数,并返回一个合并后的数组;2、使用&quot;+&quot;运算符,将两个数组合并为一个新数组,并返回结果;3、使用array_merge_recursive()函数,用于合并两个或多个数组,并且可以处理多维数组的合并;4、使用array_replace()函数等等。本教程操作环境:windows10系统、php8.1.3版本、DELL G3电脑。在PHP中,数组合并是一种常见的操作,它可以
发表于:2023-12-06 浏览:406 TAG:
【PHP】7个php字符串处理函数有哪些
7个php字符串处理函数有strlen()、strpos()、substr()、str_replace()、strtolower()、strtoupper()、trim()等。详细介绍:1、strlen(),用于获取字符串的长度;2、strpos(),用于查找字符串中的特定子串,返回第一次出现位置;3、substr(),用于获取字符串的子串;4、str_replace()等等。本教程操作系统:Windows10系统、PHP8.1.3版本、Dell G3电脑。在PHP中,有许多可以用于字
发表于:2023-12-04 浏览:694 TAG:
【PHP】php中魔术常量有哪些
常用的魔术常量有:1、LINE,当前行号的数字表示;2、FILE,当前文件的完整路径和文件名;3、DIR,当前文件所在的目录;4、FUNCTION,当前函数的名称;5、CLASS,当前类的名称;6、TRAIT,当前特性的名称;7、METHOD,当前方法的名称;8、NAMESPACE,当前命名空间的名称等等。【程序员必备开发工具推荐】Apifox一款免费API管理工具Apifox = Postman + Swagger + Mock + JMeter本教程操作系统:windows10系统
发表于:2023-12-06 浏览:374 TAG:
【PHP】thinkphp设计模式讲解
一、设计模式简介 &nbsp;首先我们来认识一下什么是设计模式: &nbsp;设计模式是一套被反复使用、容易被他人理解的、可靠的代码设计经验的总结。 &nbsp;设计模式不是Java的专利,我们用面向对象的方法在PHP里也能很好的使用23种设计模式。 &nbsp;那么我们常说的架构、框架和设计模式有什么关系呢? &nbsp;架构是一套体系结构,是项目的整体解决方案;框架是可供复用的半成品软件,是具体程序代码。架构一般会涉及到采用什么样的框架来加速和优化某部分问题的解决,而好的框架代码里合理使用了很多设计模式。 &nbsp;二、提炼设计模式的几个原则: &nbsp;
发表于:2024-06-24 浏览:246 TAG:
【PHP】php函数find的用法
在php的开发中,有很多常用函数可以帮助我们快速完成一些操作,其中常用的一个函数是find函数。这个函数的作用是用于查找字符串中的特定字符或子字符串。本篇文章将详细介绍php函数find的用法。基本语法find函数的基本语法非常简单,只需要在字符串中调用该函数并传递要查找的字符或子字符串作为参数即可。例如:$string&nbsp;=&nbsp;&quot;Hello&nbsp;World!&quot;; $find&nbsp;=&nbsp;&quot;W&quot;; $result
发表于:2023-12-29 浏览:307 TAG: