浅谈KOA2 Restful方式路由初探
前言
最近考虑将服务器资源整合一下,作为多端调用的API
看到Restful标准和ORM眼前一亮,但是找了不少版本路由写的都比较麻烦,于是自己折腾了半天
API库结构
考虑到全部对象置于顶层将会造成对象名越来长,同时不便于维护,故采取部分的分层结构
如workflow模块内的prototypes,instances等等,分层的深度定义为层级
可访问的对象集合(collection)的属性满足Restful设计
--workflow(category) --prototypes(collection) --[method]... --[method]... --instances(collection) --users(collection) --[method]List#get:object/ --[method]Instance#get:object/:id --... --...
RESTFULAPI接口
将RestfulAPI接口进行标准化命名
.get('/',ctx=>{ctx.error('路径匹配失败')}) .get('/:object',RestfulAPIMethods.List) .get('/:object/:id',RestfulAPIMethods.Get) .post('/:object',RestfulAPIMethods.Post) .put('/:object/:id',RestfulAPIMethods.Replace) .patch('/:object/:id',RestfulAPIMethods.Patch) .delete('/:object/:id',RestfulAPIMethods.Delete) .get('/:object/:id/:related',RestfulAPIMethods.Related) .post('/:object/:id/:related',RestfulAPIMethods.AddRelated) .delete('/:object/:id/:related/:relatedId',RestfulAPIMethods.DelRelated)
API对象
这个文件是来自微信小程序demo,觉得很方便就拿来用了,放于需要引用的根目录,引用后直接获得文件目录结构API对象
const_=require('lodash') constfs=require('fs') constpath=require('path') /** *映射d文件夹下的文件为模块 */ constmapDir=d=>{ consttree={} //获得当前文件夹下的所有的文件夹和文件 const[dirs,files]=_(fs.readdirSync(d)).partition(p=>fs.statSync(path.join(d,p)).isDirectory()) //映射文件夹 dirs.forEach(dir=>{ tree[dir]=mapDir(path.join(d,dir)) }) //映射文件 files.forEach(file=>{ if(path.extname(file)==='.js'){ tree[path.basename(file,'.js')]=require(path.join(d,file)) tree[path.basename(file,'.js')].isCollection=true } }) returntree } //默认导出当前文件夹下的映射 module.exports=mapDir(path.join(__dirname))
koa-router分层路由的实现
创建多层路由及其传递关系
执行顺序为
1--路径匹配
--匹配到‘/'结束
--匹配到对应的RestfulAPI执行并结束
--继续
2--传递中间件Nest
3--下一级路由
4--循环to1
constDefinedRouterDepth=2 letrouters=[] for(leti=0;i{ //根据版本号选择库 letapiVersion=ctx.headers['api-version'] ctx.debug(`-------(API版本[${apiVersion}])--=-------`) if(!apiVersion){ ctx.error('版本号未标记') return } letAPIRoot=null try{ APIRoot=require(`../restful/${apiVersion}`) }catch(e){ ctx.error('API不存在,请检查Header中的版本号') return } ctx.debug(APIRoot) ctx.apiRoot=APIRoot ctx.debug('---------------------------------------------') //for(leti=0;i<) awaitnext() }) } route .get('/',ctx=>{ctx.error('路径匹配失败')}) .get('/:object',RestfulAPIMethods.List) .get('/:object/:id',RestfulAPIMethods.Get) .post('/:object',RestfulAPIMethods.Post) .put('/:object/:id',RestfulAPIMethods.Replace) .patch('/:object/:id',RestfulAPIMethods.Patch) .delete('/:object/:id',RestfulAPIMethods.Delete) .get('/:object/:id/:related',RestfulAPIMethods.Related) .post('/:object/:id/:related',RestfulAPIMethods.AddRelated) .delete('/:object/:id/:related/:relatedId',RestfulAPIMethods.DelRelated) if(i!=0){ route.use('/:object',Nest,routers[i-1].routes()) } routers.push(route) } let=router=routers[routers.length-1]
Nest中间件
将ctx.apiObject设置为当前层的API对象
constNest=async(ctx,next)=>{ letobject=ctx.params.object letapiObject=ctx.apiObject||ctx.apiRoot if(!apiObject){ ctx.error('API装载异常') return } if(apiObject[object]){ ctx.debug(`ctx.apiObject=>ctx.apiObject[object]`) ctx.debug(apiObject[object]) ctx.debug(`------------------------------------`) ctx.apiObject=apiObject[object] }else{ ctx.error(`API接口${object}不存在`) return } awaitnext() }
RestfulAPIMethods
letRestfulAPIMethods={} letMethods=['List','Get','Post','Replace','Patch','Delete','Related','AddRelated','DelRelated'] for(leti=0;i需要注意的点
1、koa-router的调用顺序
2、涉及到async注意next()需要加await以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。