如何开发rest接口服务_如何简化网络请求接口开发

9a7f9e4782ec5cef6a82d04fd8366daa.png
日常开发中,需要大量和后端对接接口,很容易写出大量的模板代码,比如把对接口的请求放到组件内,或者虽然有数据访问层,但是有大量 getpost 方法的调用,传参的字符串拼接,异常处理等等,有些逻辑是可以通过请求拦截来处理的,有些可以通过配置得到简化,本文是对这个过程的一个实践和总结。

面对的问题

首先,明确下我们要解决什么问题,因为说到网络请求调用,使用 axios 库就可以了,上手简单,提供请求拦截功能,大多数场景都可以覆盖到,为什么要再去做额外的开发?

axios 做基础的库可以满足日常开发需要,不过出于架构设计、复用和便于维护的需要,通常我们会进行分层,抽出一个数据访问逻辑层,专门去处理和后端的接口访问,这个层对上层提供清晰可读性好的接口,便于对数据进行聚合裁剪。

在这个数据访问逻辑层,通常会调用 axios 或者其他的库进行接口的访问,通常会有如下的场景,需要我们处理:

  1. 请求拦截,比如异常处理,包括网络异常、服务器端异常、登录超时等,或者要做全局 Loading 显示等
  2. 请求缓存,对于不变的数据可以缓存到内存,或者本地存储,后续不再发起新的请求
  3. Mock 数据,因为这个层对上层提供清晰的接口,可以在这一层做 MockMock 的方式可以自己组装数据,或者将请求重定向到 Mock 服务器
  4. 请求合并,这个需求可能用的比较少,比如在某些需求下,有两个组件公用一个接口,但是两个组件又相互独立,又没有共享数据状态,如果两个组件刚好在一个页面,就会导致页面加载时同时发出两个相同的请求,如何合并两个请求呢?
  5. 安全检查,某些接口对安全要求比较高,需要对数据进行检查、防止脚步注入等问题。

以上是我总结的一些需求,不知道大家有没有类似的场景,针对这些需求,大家是如何满足的呢?

实现目标

针对以上问题,我们希望通过简单的配置即可满足需要,简化网络请求实现,提高接口对接效率,将开发者的注意力集中在UI层的交互和业务逻辑开发。

具体如下:

  1. 简单可配置,提供全局的配置,以及单一接口的配置,单一接口的配置可以覆盖全局的配置
  2. 请求拦截,利用 Promise 来做请求拦截,对外提供一个 filter 函数,暴露给用户自定义拦截需求
  3. 请求合并,针对几乎是同时发出的请求,只需要一次请求即可,后续请求复用第一个的结果
  4. 请求缓存,针对不同场景提供可选的存储项,比如内存、localStoragesessionStorage
  5. Mock,对外提供 mock 函数,可以全局配置,也可以针对单个接口配置
  6. 安全检查,利用 xss 过滤库,做安全检查,加入 csrf token 防止伪造请求。

实现

简单可配置

示例:

全局配置:

import { buildApi, http } from 'biz-lib';
let count = 0;
export default function (opts) {return buildApi(opts, {isDev:process.env.NODE_ENV === 'development',   /*** 统一设置请求域名*/host:'http://exam.china.com',/*** 将请求定向到 mock 服务器*/     mock(url,option) {return http.get(`${mock.host}/mockjsdata/${mock.projectId}${url}`);},/*** 请求执行前*/before() {Loading.show('请稍后...');count++;},/*** 请求执行后*/after() {count--;if (count <= 0) {Loading.hide();count = 0;}},/** * 过滤器,对请求预处理,和后端阅读 code 值,* code = 1 直接返回数据,其他可以抛异常,或自定义处理*/filters: [function (res) {if (res.code == 1) {return res.data;} else if (res.code === -1) {throw new CodeError(-1, res.msg);} else if (res.code === 100) {throw new CodeError(100, '您尚未登录');}return res;},],// 统一处理异常,onError(err) {Loading.hide();count = 0;if (typeof err.code === 'undefined' || err.code === -1 ) {message.warning(err.message);} else if (err.code === 100) {window.location.href='/login'}throw err;},});
}

单一接口配置示例:

import { buildApi } from './api';
const apis = buildApi({/*** POST 请求示例*/'submitAnswer': {url: '/cexam/api/answer/submit/{id}'method:'GET' | 'POST' | 'Jsonp',format:'form' | 'json' | 'form-data',cache: true | false,storage:'sessionStorage' | 'localStorage' | 'memoryStorage',merge: true | false,mock:function(url,data,option){},before:function(){},after:function(){},filters:[],headers:{},},/*** GET 请求示例*/'getQuestionList': '/cexam/api/exam/group/list/{id}' : 
});export const submitAnswer=(id:string,data:IParams)=>{// 调用post请求return apis.submitAnswer({id},{data})
}export const getQuestionList=(id:string)=>{// get请求apis.getQuestionList({id})
}

接口逻辑层需要对调用方提供可读的 API,可以利用 Typescript 对接口进行定义,调用方调用体验会很好。

配置项说明:

  • method 请求类型,包括:POST/GET
  • format 请求数据格式,包括:json/form/form-data
  • cache 缓存请求数据(不刷新浏览器的情况下)
  • storage 可以将请求缓存到存储,包括 sessionStorage/localStorage/memoryStorage
  • merge 相同接口请求是否合并
  • before 请求发起之前执行
  • after 请求发起之后执行
  • filters 函数式一个函数数组,前一个函数的输出是后一个函数的输入
  • mock 提供请求的 mock 方法,自定义 mock
  • headers 自定义请求头
  • url 请求的 url,可以内嵌参数,比如 list/{id}
  • 参数 通过大括号 {} 设置,通过方法的第一次参数指定,和 {} 中设定的同名即可

请求响应拦截

提供请求响应拦截功能,处理通用业务逻辑,比如: - 请求之前和请求之后显示和隐藏全局 Loading - 请求返回后预处理返回数据,减少调用端代码 - 统一处理例外情况,比如异常,登录超时,账号余额不足等等。

统一异常处理的前提是后端返回的规范的数据结构,比如{code:0,data:'',message:''},约定 code 值,code 等于多少是请求正常,多少是异常,以及其他例外情况。

  • 网络通信异常
  • 程序执行异常
  • 非异常的例外情况,比如登录超时、考试已结束、余额不足等

可以针对不同的异常进行编码,方便接口调用方捕获异常后进行自定义处理,类似后端的自定义异常类型,但是后端可以根据类型进行捕获,前端是弱类型,只好靠编码来识别异常了。

示例如下:

let apis=buildApi({'submitAnswer': {method: 'POST',url: '/cexam/api/answer/submit'}
}, {filters: [function (res) {if (res.code == 1) {// code = 1 直接返回数据return res.data;} else if (res.code == -1) {throw new CommonlError(-1, res.message);} else if (res.code == -2) {// 考试已结束处理               throw new ExamTerminalError(-2, '考试已结束');} else if (res.code == -3) {// 余额不足处理throw new CommonlError(-3, res.message);}  else if (res.code == 10) {// 登录超时处理return window.location.href = '/login';}return res;},function (res){return res;}],//统一处理异常,onError(err) {if (err['code'] == -1) {message.warning(err.message);}throw err;}
});

调用

try{let data = await apis.submitAnswer();await apis.operationA(data);await apis.operationB();
}catch(err){if(err.code==-2){//处理考试结束的例外情况}else if(err.code == -3){//处理余额不足}
}

经过请求预处理,正常情况下直接返回后端数据,不需要判断 code 值,统一异常处理以后,通过 catch 捕获异常,自定义处理逻辑。

整体的编程体验很类似 Java 或者 C#

请求合并

前文提到了需要请求合并的场景,比如有两个独立的组件,但是使用了相同的一个接口,即希望组件相互独立没有依赖,又希望相同请求只请求一次。

每个使用 buid-api 的地方都需要配置merge:true,可以共享一次请求。

const api1 = buildApis({'getProjectAuth':{method:'GET',merge:true,url:'/api/project/auth'}
});
const api2 = buildApis({'getProjectAuth':{method:'GET',merge:true,url:'/api/project/auth'}
});
//如果api1调用过,api2会复用api1的返回结果

请求合并的实现比较取巧,如果判断有相同的请求,只要第二个请求复用第一个请求返回的 Promise 即可,

请求缓存

针对需要多次访问的请求,数据不变的话,可以设置缓存。

可以设置缓存的存储,默认是 memoryStorage,用户可以自定义 storage 的实现。

const api1 = buildApis({'getProjectAuth':{method:'GET',cache:true,storage:'sessionStorage' | 'localStorage' | 'memoryStorage',url:'/api/project/auth'}
});
const api1 = buildApis({'getProjectAuth':{method:'GET',cache:true,storage:{get(key){},set(key,value){}},url:'/api/project/auth'}
});

MOCK 数据

可以提供统一的 mock配置,或者单独配置,单独配置的 mock 优先执行。

具体 mock 采用什么技术,由调用方决定,比如可以使用 json,或者 rap,或者 mockjs 库等。

如果采用本地 node 代理,可以不用设置 mock

const apis = buildApi({'submitAnswer': {method: 'POST/GET',format:'json/form/form-data',url: '/cexam/api/answer/submit',mock(url,data,option){return {id:1,name:'test'};}},'getQuestionList': '/cexam/api/exam/group/list/{id}' : 
},{mock(url,data,option) {return http.get(`${RAP.host}/mockjsdata/${RAP.projectId}${url}`);},
});

安全检查

统一提供安全检查过滤,针对参数以及返回数据进行 xss 过滤,csrf token 添加,可以参考 axios 的方式。

最后

本文总结了常见的网络接口对接开发过程中常见的问题,并且针对需求提供了一个简单可配置的方案,极大的简化网络接口对接开发,提供了包括:请求响应拦截,合并,缓存,统一异常处理,Mock 等功能,简化了接口的调用,提升开发效率。

码字不易,觉得有收获就随手给个赞呗,谢谢^_^!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OkHttp协议介绍以及文件下载和上传+OkHttp协议封装+OkHttp拦截器____SpringBoot——集成Okhttp3

OkHttp协议 okhttp是一个第三方类库&#xff0c;用于android中请求网络 这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) 文件下载用Get方式 OkHttpClient okHttpClient new OkHttpClient.Builder().callTimeout…

质量属性效用树例子_数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

HT 是啥&#xff1a;Everything you need to create cutting-edge 2D and 3D visualization.这口号是当年心目中的产品方向&#xff0c;接着就朝这个方向慢慢打磨&#xff0c;如今 HT 算是达到了这样的效果&#xff0c;谈不上用尽洪荒之力&#xff0c;但我们对产品结果很满意&a…

linux vi 出现下划线,Vim高亮当前行(显示为下划线)的解决方案

最近配置Vim&#xff0c;由于以前的vimrc早已丢失&#xff0c;只好重新配置一份&#xff0c;此为题外话&#xff0c;略过不提…在Vim中&#xff0c;可以选择开启高亮当前行&#xff0c;这是一个很不错的特性。开启它也很简单&#xff0c;只需要在vimrc中加入这么一行&#xff1…

springBoot 简单优雅是实现文件上传和下载

前言 好久没有更新spring Boot 这个项目了。最近看了一下docker 的知识&#xff0c;后期打算将spring boot 和docker 结合起来。刚好最近有一个上传文件的工作呢&#xff0c;刚好就想起这个脚手架&#xff0c;将文件上传和下载整理进来。 配置 在application.properties 中增…

C语言的VC开发环境界面介绍,【c语言在vc++6.0中编写界面程序】

到现在为止&#xff0c;C 仍然是计算机编程领域的经典语言之一&#xff0c;C 17 标准在2017上半年已经探讨确定。本期我们汇集了编程专家——祁宇(《深入应用 C 11》作者&#xff0c;C 开源社区 purecpp.org 创始人)的多年心得小结&#xff0c;并具体介绍了 C 17 最新标准中值得…

SpringBoot+VUE 前端加密算法 RSA+DES

前言 为了提高用户登陆的安全性&#xff0c;公司准备整理一份相对安全的登陆模式。 想法 主流加密算法 主流加密算法 &#xff08;一&#xff09;对称加密AES ,其特点是&#xff1a;算法简单&#xff0c;加密速度快&#xff1b; &#xff08;二&#xff09;非对称加密方式&…

spring cloud微服务_年后进大厂,必备这份微服务面试题:Dubbo+SpringBoot+Cloud

Dubbo面试题Dubbo与DubboX区别Dubbo中zookeeper做注册中心&#xff0c;如果注册中心集群都挂掉&#xff0c;发布者和订阅者之间还能通信么&#xff1f;Dubbo中有哪些角色&#xff1f;Dubbo在安全机制方面是如何解决的Dubbo执行流程&#xff1f;Dubbo支持的协议有哪些&#xff1…

c语言交通违章编程代码,C语言程序设计之交通处罚单管理系统 报告(内含代码).doc...

C语言程序设计姓名&#xff1a;张强强学号&#xff1a;20121003695班序号&#xff1a;011121前言&#xff1a;C语言是近年来国内得到迅速推广使用的一种计算机语言。C语言程序设计课程是计算机专业和信息管理专业的核心专业基础课&#xff0c;无论是计算机专业还是非计算器专业…

前端 - token 是什么?为什么每次请求头(HEADS)里要携带它?___请求时,为什么要携带token?

前端 - token 是什么&#xff1f;为什么每次请求头&#xff08;HEADS&#xff09;里要携带它&#xff1f; Token token 是客户端频繁向服务器端请求数据&#xff0c;服务器频繁的去数据库查询用户名和密码进行对比&#xff0c;判断用户名和密码正确与否&#xff0c;并作出相应…

全栈工程师薪水_2020 Java 全栈工程师进阶路线图,不可错过

技术更新日新月异&#xff0c;对于初入职场或者刚开始学习的同学来说&#xff0c;经常会困惑该往那个方向发展&#xff0c;这一点所有刚开始学习的人基本都有这个体会的。刚开始学习 Java 那会&#xff0c;最大的问题就是不知道该学什么&#xff0c;以及学习的顺序&#xff0c;…

5乘7的c语言程序,C语言程序设计实验5-7教案(20页)-原创力文档

第 7-8 次课程名称 程序设计基础 课程性质 实验课授课班级 网络 16-1 、2 授课地点 14022016 年 11 月 9 日第 5 小节 ~第 8 小节授课时间 2016 年 11 月 16 日第 5 小节~第 8 小节2016 年 11 月 23 日第 5 小节~第 8 小节课题&#xff1a; 实验六、 数组的应用—— 4 学时主要…

python手机安装模块_python如何安装模块 模块安装操作教程

Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言&#xff0c;设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&#xff0c;它具有比其他语言更有特色语法结构。那么Python的安装模块该怎么使用呢&#xff1f;让小编来教一下各位吧。模…

cookie 和 token 都存放在 header 中,为什么不会劫持 token?____token和cookie的区别

cookie 和 token 都存放在 header 中&#xff0c;为什么不会劫持 token&#xff1f; cookie:登录后服务端生成的sessionid&#xff0c;并在http请求里返回到客户端&#xff0c;同时服务端保存sessionid&#xff0c;以后客户端的每次http请求都带上cookie&#xff08;sessionid…

语言inc c,汇编语言练习

习题一1&#xff0e;在计算机内部&#xff0c;计算机能够直接执行的程序语言是。A&#xff0e;汇编语言 B。C语言C&#xff0e;机器语言 D。高级语言2&#xff0e;在堆栈段中&#xff0c;存放栈顶地址的寄存器是。A&#xff0e;IP &#xff22;&#xff0e;SP &#xff23;&…

python降维之时间类型数据的处理_使用Python进行数据降维|线性降维

前言为什么要进行数据降维&#xff1f;直观地好处是维度降低了&#xff0c;便于计算和可视化&#xff0c;其深层次的意义在于有效信息的提取综合及无用信息的摈弃&#xff0c;并且数据降维保留了原始数据的信息&#xff0c;我们就可以用降维的数据进行机器学习模型的训练和预测…

cookie、Session、Token、sessionStorage、localStorage简介__Token放在 cookie, sessionStorage 和 localStorage中区别

cookie、Session、Token、sessionStorage、localStorage简介 cookie 是一个非常具体的东西&#xff0c;只得是浏览器里永久存储的一种数据&#xff0c;是浏览器实现的一种数据存储功能。Cookie在计算机中是个存储在浏览器目录中的文本文件&#xff0c;当浏览器运行时&#xf…

歌星大奖赛C语言程序,C_歌星大奖赛

在歌星大奖赛中&#xff0c;有10个评委为参赛的选手打分&#xff0c;分数为1~100分。选手最后得分为&#xff1a;去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。*问题分析与算法设计这个问题的算法十分简单&#xff0c;但是要注意在程序中判断最大、最…

c语言树莓派音乐播放器,使用web端来控制我的树莓派播放音乐

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;web端控制树莓派播放音乐&#xff0c;PHPNodeJSmpg123&#xff0c;粗糙版。实现后还可以做个app什么的。代码git用到的代码内容可以在这里看~nodempg.js启动一个se…

Nginx学习_狂神

Nginx 公司产品出现瓶颈&#xff1f; 我们公司项目刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#xff0c;所以在低并发的情况下&#xff0c;一个jar包启动应用就够了&#xff0c;然后内部tomcat返回内容给用户。 但是慢慢的&#xff0c;使用我们平台的用户…

c语言中运算符的读音是什么,操作符、运算符,operator,音标,读音,翻译,英文例句,英语词典...

补充资料&#xff1a;二进制算术运算二进制算术运算binary arithmetic operation二.165. 原码两位索法为了提高运算速度&#xff0c;在1次操作中可同时考虑两位乘数&#xff0c;求得与两位乘数相对应的部分积&#xff0c;其速度比一位乘法提商1倍&#xff0c;规则如下: 又丫1二…