浅谈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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。