距离上一篇关于Web API的文章(如何实现RESTful
Web API的身份验证)有好些时间了,在那篇文章中提到的方法是非常简单而有效的,我在实际的项目中就这么用了,代码经过一段时间的磨合,已经很稳定了,所以我打算写篇总结,并在最近这段时间里提供一个ASP.net Web API的综合例子。
对四个HTTP方法的理解
众所周知,HTTP有四个方法,GET、POST、PUT和DELETE,分别对应数据库的SELECT、INSERT、UPDATE和DELETE,一般的教程说到这里也就Over了,其实光是知道这个还不够,还不足以把各种业务操作转变为这四个方法。下面我给出一些设计思路,这是我自行实践的总结,如有谬误,请不吝指正:
GET
没错,就是SELECT,如果这个业务操作不会改变服务器的数据,那么就可以将它抽象成GET方法,但也不绝对,比如很多网站提供了文件下载,按理说下载应该是不会改变服务器数据的,所以用GET,但很多时候服务器还提供了下载计数,你说这算不算改变了服务器的数据?——这种情况一般不算,所以依然用GET。下面是GET方法的举例:
- 获取所有员工列表
- 按条件分页查询某些员工信息
- 获取一个员工的信息
- 下载一个文件
- 获取当前输入的商品的价格
这么看来GET可是使用相当多的方法。
PUT
UPDATE一条记录就抽象成PUT方法,那这个动作是不是也会用得很多呢?这个比你想像中的少得多,为什么?因为大量的修改记录的动作都不只是一个简单的UPDATE动作,比如用户要撤销一个订单,这个操作表面上看起来是修改一条订单记录的状态为“撤销”,但实际上比这个要复杂得多,我们的订货是有流程的,用户撤销一个订单其实只是向我们的服务器提出了一个撤销订单的请求,让这个订单转入了撤销流程,而不是简单地修改订单记录的状态,这里面有一连串的动作,比如:等待管理员确认,更新应收款信息,将已出库的货物重新入库,写操作日志,发送系统通知等等,所以这个动作应该是POST,而不是PUT,大多数涉及业务流程的东西都是POST,这个我后面会再提到,而PUT则用于简单的,不涉及业务流程的数据库单条记录UPDATE,例如:
- 用户修改自己的个人信息(假设这个修改动作不需要审批)
- 用户编辑了一张暂存(未转入执行流程)的订单
POST
表面上看起来对应到数据库的一次INSERT,但实际上对比PUT,POST的使用是广泛很多的,可以说大多数业务操作都会被抽象成POST方法,例如:
- 新增一个用户
- 提交一个订单
- 撤销一个订单
- 付款
- 给员工发放工资
- 提交一个基础资料的修改申请(需要审批)
- 激活一个产品
- 驳回一个员工的申请
想想看上述的这些动作往往涉及到数据库的若干张表的一系列的变化,这个时候就不能简单地使用PUT,而是应该使用POST,代表“提交了一个XX的请求”,理解这点很关键。
DELETE
对应SQL语句的DELETE,表示删除一个对象,是不是应该使用也很多呢?其实跟PUT一样,使用得比你想像的少,因为大多数时候,我们的数据库所执行的“删除”都不是简单的DELETE,甚至大多数对象,我们都不会提供直接的删除,例如用户,为了保证数据的完整性,我们在数据库中使用了许多的外键约束,要直接DELETE一条用户记录是不会成功的,我们只能“停用”一个用户,表示此用户不再生效。当然了,话不是那么绝对,如果这是个刚刚增加的用户并且没有在其它表中引用到它,那么确实可以直接把它DELETE掉,这种情况出现在管理员刚刚添加了一个用户,但发现用户名输错了,而用户名却是无法修改的,管理员只能尝试删除这个用户然后重新添加,或者“停用”掉这个错误的用户,只是这么一来会产生一条完全没意义的用户记录。DELETE用于你认为需要提供DELETE方法的场合(很多时候其实不需要,这取决于你的设计),例如:
- 删除一个用户(很可能执行失败)
- 删除一条暂存的订单(此订单尚未转入处理流程)
- 删除一条系统消息
更具体的动作描述
为了表达得更具体些,我就把上面举的这些例子转变为具体化的URI及动作描述:
操作 |
URI |
HTTP方法 |
说明 |
获取所有员工列表 |
/api/emp/employees |
GET |
|
按条件分页查询某些员工信息 |
/api/emp/employees?sex=m&page=1&numberperpage=20 |
GET |
在URI中带上参数 |
获取一个员工的信息 |
/api/emp/employees/58 |
GET |
58是员工的ID,当然你也可以设计成用户名 |
下载一个文件 |
/api/fileservice/files/2832 |
GET |
2832是文件的ID,当然你可以设计成文件名或者GUID |
获取当前输入的商品的价格 |
/api/sale/goods/32680 |
GET |
32680是商品的ID |
用户修改自己的个人信息(假设这个修改动作不需要审批) |
/api/admin/users/8642 |
PUT |
8642是用户的ID,另外要带上修改所需要的各种信息 |
用户编辑了一张暂存(未转入执行流程)的订单 |
/api/sale/orders/234892 |
PUT |
234892是订单的ID,另外要带上修改订单所需的各种信息 |
新增一个用户 |
/api/admin/users |
POST |
带上新增用户所需要的信息 |
提交一个订单 |
/api/sale/orders |
POST |
带上订单完整信息 |
付款 |
/api/sale/pay |
POST |
付款完整信息,将包含要支付的订单的ID等信息 |
给员工发放工资 |
/api/emp/paysalary |
POST |
带上发放工资的完整信息,将包括员工ID,发放工资的月份和金额等 |
提交一个基础资料的修改申请(需要审批) |
/api/basic/modifymanufacture |
POST |
带上要修改的对象的完整信息,包括ID等 |
激活一个产品 |
/api/sale/activateproduct |
POST |
带上要激活的产品的相关信息,包括ID等 |
驳回一个员工的申请 |
/api/admin/approve |
POST |
带上申请ID、驳回原因等 |
删除一个用户(很可能执行失败) |
/api/admin/users/567 |
DELETE |
567为要删除的用户的ID |
删除一条暂存的订单(此订单尚未转入处理流程) |
/api/sale/orders/234892 |
DELETE |
234892为订单ID |
删除一条系统消息 |
/api/sys/messages/1008689021 |
DELETE |
1008689021为系统消息的ID |
URI中的“api”是固定的,用于区别于普通的网页的URI,接下去的“emp”、“fileservice”、“sale”、“admin”、“basic”和“sys”等可看作是分类,例如“给员工发放工资”和“员工信息”这两个“资源”都是放在“emp”这个分类中的,剩余的部分是对象名称,或称资源名称,其实准确地说,完整的URI地址才是真正的资源名称,为什么叫资源?google一下RESTful Web API,看看RESTful的“R”就理解了,简单地说,我们把各种操作都最终抽象为资源,一切业务操作(不管多复杂)都转变为对某个资源的增删查改,也就是上面提到的四个HTTP的方法。
GET、PUT和DELETE方法都比较显而易见,好理解,大多数时候,这几个方法的资源都确确实实对应着数据库的某张表或某条记录,例如“/api/admin/users”可能对应着数据库中的ADMIN_USER表,而“/api/admin/users/8642”则对应着ADMIN_USER表中的ID为8642的这条用户记录。
POST方法则不是那么直截了当,例如“/api/emp/paysalary”,也许数据库中根本就没有一个直接与之一一对应的表,paysalary是一个抽象的业务操作对象,往这个对象执行一下POST就相当于给某个员工发放了一次工资,其实际的动作可能涉及到多张表的联动,如员工表的工资发放标志、工资发放记录表插入一条记录,公司财务表插入一条记录,操作日志表插入一条记录,系统消息表插入一条记录等……
这就是我对Web API的设计的理解,大家看看有什么问题?
距离上一篇关于Web API的文章(如何实现RESTful
Web API的身份验证)有好些时间了,在那篇文章中提到的方法是非常简单而有效的,我在实际的项目中就这么用了,代码经过一段时间的磨合,已经很稳定了,所以我打算写篇总结,并在最近这段时间里提供一个ASP.net Web API的综合例子。
对四个HTTP方法的理解
众所周知,HTTP有四个方法,GET、POST、PUT和DELETE,分别对应数据库的SELECT、INSERT、UPDATE和DELETE,一般的教程说到这里也就Over了,其实光是知道这个还不够,还不足以把各种业务操作转变为这四个方法。下面我给出一些设计思路,这是我自行实践的总结,如有谬误,请不吝指正:
GET
没错,就是SELECT,如果这个业务操作不会改变服务器的数据,那么就可以将它抽象成GET方法,但也不绝对,比如很多网站提供了文件下载,按理说下载应该是不会改变服务器数据的,所以用GET,但很多时候服务器还提供了下载计数,你说这算不算改变了服务器的数据?——这种情况一般不算,所以依然用GET。下面是GET方法的举例:
- 获取所有员工列表
- 按条件分页查询某些员工信息
- 获取一个员工的信息
- 下载一个文件
- 获取当前输入的商品的价格
这么看来GET可是使用相当多的方法。
PUT
UPDATE一条记录就抽象成PUT方法,那这个动作是不是也会用得很多呢?这个比你想像中的少得多,为什么?因为大量的修改记录的动作都不只是一个简单的UPDATE动作,比如用户要撤销一个订单,这个操作表面上看起来是修改一条订单记录的状态为“撤销”,但实际上比这个要复杂得多,我们的订货是有流程的,用户撤销一个订单其实只是向我们的服务器提出了一个撤销订单的请求,让这个订单转入了撤销流程,而不是简单地修改订单记录的状态,这里面有一连串的动作,比如:等待管理员确认,更新应收款信息,将已出库的货物重新入库,写操作日志,发送系统通知等等,所以这个动作应该是POST,而不是PUT,大多数涉及业务流程的东西都是POST,这个我后面会再提到,而PUT则用于简单的,不涉及业务流程的数据库单条记录UPDATE,例如:
- 用户修改自己的个人信息(假设这个修改动作不需要审批)
- 用户编辑了一张暂存(未转入执行流程)的订单
POST
表面上看起来对应到数据库的一次INSERT,但实际上对比PUT,POST的使用是广泛很多的,可以说大多数业务操作都会被抽象成POST方法,例如:
- 新增一个用户
- 提交一个订单
- 撤销一个订单
- 付款
- 给员工发放工资
- 提交一个基础资料的修改申请(需要审批)
- 激活一个产品
- 驳回一个员工的申请
想想看上述的这些动作往往涉及到数据库的若干张表的一系列的变化,这个时候就不能简单地使用PUT,而是应该使用POST,代表“提交了一个XX的请求”,理解这点很关键。
DELETE
对应SQL语句的DELETE,表示删除一个对象,是不是应该使用也很多呢?其实跟PUT一样,使用得比你想像的少,因为大多数时候,我们的数据库所执行的“删除”都不是简单的DELETE,甚至大多数对象,我们都不会提供直接的删除,例如用户,为了保证数据的完整性,我们在数据库中使用了许多的外键约束,要直接DELETE一条用户记录是不会成功的,我们只能“停用”一个用户,表示此用户不再生效。当然了,话不是那么绝对,如果这是个刚刚增加的用户并且没有在其它表中引用到它,那么确实可以直接把它DELETE掉,这种情况出现在管理员刚刚添加了一个用户,但发现用户名输错了,而用户名却是无法修改的,管理员只能尝试删除这个用户然后重新添加,或者“停用”掉这个错误的用户,只是这么一来会产生一条完全没意义的用户记录。DELETE用于你认为需要提供DELETE方法的场合(很多时候其实不需要,这取决于你的设计),例如:
- 删除一个用户(很可能执行失败)
- 删除一条暂存的订单(此订单尚未转入处理流程)
- 删除一条系统消息
更具体的动作描述
为了表达得更具体些,我就把上面举的这些例子转变为具体化的URI及动作描述:
操作 |
URI |
HTTP方法 |
说明 |
获取所有员工列表 |
/api/emp/employees |
GET |
|
按条件分页查询某些员工信息 |
/api/emp/employees?sex=m&page=1&numberperpage=20 |
GET |
在URI中带上参数 |
获取一个员工的信息 |
/api/emp/employees/58 |
GET |
58是员工的ID,当然你也可以设计成用户名 |
下载一个文件 |
/api/fileservice/files/2832 |
GET |
2832是文件的ID,当然你可以设计成文件名或者GUID |
获取当前输入的商品的价格 |
/api/sale/goods/32680 |
GET |
32680是商品的ID |
用户修改自己的个人信息(假设这个修改动作不需要审批) |
/api/admin/users/8642 |
PUT |
8642是用户的ID,另外要带上修改所需要的各种信息 |
用户编辑了一张暂存(未转入执行流程)的订单 |
/api/sale/orders/234892 |
PUT |
234892是订单的ID,另外要带上修改订单所需的各种信息 |
新增一个用户 |
/api/admin/users |
POST |
带上新增用户所需要的信息 |
提交一个订单 |
/api/sale/orders |
POST |
带上订单完整信息 |
付款 |
/api/sale/pay |
POST |
付款完整信息,将包含要支付的订单的ID等信息 |
给员工发放工资 |
/api/emp/paysalary |
POST |
带上发放工资的完整信息,将包括员工ID,发放工资的月份和金额等 |
提交一个基础资料的修改申请(需要审批) |
/api/basic/modifymanufacture |
POST |
带上要修改的对象的完整信息,包括ID等 |
激活一个产品 |
/api/sale/activateproduct |
POST |
带上要激活的产品的相关信息,包括ID等 |
驳回一个员工的申请 |
/api/admin/approve |
POST |
带上申请ID、驳回原因等 |
删除一个用户(很可能执行失败) |
/api/admin/users/567 |
DELETE |
567为要删除的用户的ID |
删除一条暂存的订单(此订单尚未转入处理流程) |
/api/sale/orders/234892 |
DELETE |
234892为订单ID |
删除一条系统消息 |
/api/sys/messages/1008689021 |
DELETE |
1008689021为系统消息的ID |
URI中的“api”是固定的,用于区别于普通的网页的URI,接下去的“emp”、“fileservice”、“sale”、“admin”、“basic”和“sys”等可看作是分类,例如“给员工发放工资”和“员工信息”这两个“资源”都是放在“emp”这个分类中的,剩余的部分是对象名称,或称资源名称,其实准确地说,完整的URI地址才是真正的资源名称,为什么叫资源?google一下RESTful Web API,看看RESTful的“R”就理解了,简单地说,我们把各种操作都最终抽象为资源,一切业务操作(不管多复杂)都转变为对某个资源的增删查改,也就是上面提到的四个HTTP的方法。
GET、PUT和DELETE方法都比较显而易见,好理解,大多数时候,这几个方法的资源都确确实实对应着数据库的某张表或某条记录,例如“/api/admin/users”可能对应着数据库中的ADMIN_USER表,而“/api/admin/users/8642”则对应着ADMIN_USER表中的ID为8642的这条用户记录。
POST方法则不是那么直截了当,例如“/api/emp/paysalary”,也许数据库中根本就没有一个直接与之一一对应的表,paysalary是一个抽象的业务操作对象,往这个对象执行一下POST就相当于给某个员工发放了一次工资,其实际的动作可能涉及到多张表的联动,如员工表的工资发放标志、工资发放记录表插入一条记录,公司财务表插入一条记录,操作日志表插入一条记录,系统消息表插入一条记录等……
这就是我对Web API的设计的理解,大家看看有什么问题?
分享到:
相关推荐
通常我们把REST也写作为REST/HTTP,在实际中往往把REST理解为基于HTTP的REST软件架构,或者更进一步把REST和HTTP看作为等同的概念。 今天,HTTP是互联网上应用最广泛的计算机协议。HTTP不是一个简单的运载数据的...
这篇论文定义了一个框架,致力于通过架构风格来理解软件架构,并且展示如何使用风格来指导基于网络的应用的架构设计。本文使用了一个对基于网络的应用的架构风格的调查, 根据不同的风格在分布式超媒体的架构中所...
介绍REST实践的书,很不错,有助于理解REST。
最初开始接触web service的时候,所有的材料上来就是一大堆的名词,SOAP, WSDL,看得头都要大了,后来提出来的REST就容易理解得多,虽然目前SOAP在企业级的web service中还有一席之地,但是在公共的Internet上,不是...
REST是中文翻译为表征状态转移(英文:Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。从字面意思来说,“表述”是很难理解是什么东西的?从论文上我们可以...
尽管如此,对于REST这个泊来品的理解,大多数人(包括一些资深的架构师)仍然停留在“盲人摸象”的阶段。常常听到各种各样关于REST的说法,例如:有人说:“我们这套新的API决定不用WebService(SOAP+WSDL),而是...
OpenAPI Specification 的目标是为 REST API 定义一个标准的、与语言无关的接口,允许人和计算机在不访问源代码、文档或通过网络的情况下发现和理解服务的功能。 通过 OpenAPI 的正确定义,消费者可以用最简答的...
django-rest-framework-tutorial 算是翻译的比较好的资料 跟着官网上做不理解,好不容易找到的资料
REST 并非标准,而是一种开发 Web 应用的架构风格,可以将其理解为一种设计模式。REST 基于 HTTP,URI,以及 XML 这些现有的广泛流行的协议和标准,伴随着 REST,HTTP 协议得到了更加正确的使用。 相较于基于 SOAP ...
切记不要自动换行! 全是我自己对它的理解和查看源码来进行中文注解的,如果注解有错请联系我进行修改。
REST架构风格是全新的针对Web应用的开发风格,是当今世界最成功的互联网超媒体分布式系统架构,它使得人们真正理解了Http协议本来面貌。随着 REST架构成为主流技术,一种全新的互联网网络应用开发的思维方式开始流行...
它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。 以下内容摘自阮一峰的文章: 一、起源 REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。 二、名称 Fielding将他对...
的作用和资源处理的内容,从而允许机器和人类理解 API 应该做什么。 REST Builder 使用 JAX-RS 规范(JAVA EE 标准之一)和 GraphQL servlet 生成 API 资源模型层和 API 实现层。 生成工具实现了访问API合约中定义的...
rest框架cetia4的教程 特点:基于Servlet API开发,可以运行于所有的Web容器中。 优点: 1. 可以充分利用Servlet API和JSP等资源,需要额外学习的概念较少,学习成本较低。 2. 对于传统的Web应用,可以使用服务器...
如果请求格式错误,即不是按照FortiGate可以理解的格式,它将失败。 要编写新的netconf请求,请使用FGT REST API架构。 检查: : 目前支持cmdb和monitor命令。 目前尚不支持某些特殊操作,例如带有POST请求的监视...
REST-VS-BPEL 此项目由D.González,A.Gherman,M.Gordo,PE Dalidec和S.Hsaini进行,是DTU 2013-2014年Web服务课程的项目。 该项目介绍了一家名为TravelGood的旅行公司。 该公司提供了一项网络服务,客户可以通过该...
本项目是对的分析,方便对rest_framework进行二进制解读,加深对rest_framework框架的理解。 我将在个人博客上配合详细文字说明对二进制分析的思路进行介绍,如果你同时学习rest_framework,替换本项目下载到你的...
GitHub的REST API OpenAPI说明该存储库包含描述。什么是OpenAPI?根据: OpenAPI规范(OAS)为HTTP API定义了标准的,与编程语言无关的接口描述,使人和计算机都可以发现和理解服务的功能,而无需访问源代码,其他...
java笔试题从一个圈内Java-Serenity-RestAssured-Cucumber-JUnit-Maven 示例 API 自动化解决方案 介绍 这是一个示例 Rest ...模式设计,代码库根据用户操作和问题分类为域模型包,以理解/验证结果。