原文地址:koa+mysql+vue+socket.io全栈开发之web api篇

目标是建立一个 web QQ的项目,使用的技术栈如下:

  1. 后端是基于koa2 的 web api 服务层,提供curd操作的http接口,登录验证使用的是 json web token,跨域方案使用的是 cors

  2. 数据库使用的是 mysql

  3. 为了实时通信,使用的是基于websocket协议的 socket.io 框架;

  4. 前端则使用的是 vue + vuex

本篇则讲叙服务端的搭建,之所以使用 koa,而不使用其他封装过的框架,比如 Egg.jsThinkjs。因为在我看来,koa2 已经够方便,插件也足够多,完全可以根据自己的需求,像搭积木一样构建出最适合业务需求的框架。这样不但摒弃了很多用不到的插件,使整个框架更加精简,也能对整个框架知根知底,减少了很多不可预知因素的影响。

当然我觉得最主要的是我比较懒?,不想再去学其他框架特有的api,特有的配置。因为前端有太多框架太多api需要掌握了,对于非互联网公认的技术标准,我觉得学习的优先级还是要靠后一点的。因为这些个框架,三天两头就冒出个热门的,简直多不胜数,学不过来啊,而koa基本都是这些框架的底层,明显靠谱多了。

基本框架搭建

这几个koa插件大部分项目八九不离十要用到:

  • koa-body 解析http数据
  • koa-compress gzip压缩
  • koa-router 路由
  • koa-static 设置静态目录
  • koa2-cors 跨域cors
  • log4js 老牌的日志组件
  • jsonwebtoken jwt 组件

基本的目录结构

public #公共目录
src    #前端目录
server #后端目录
├── common #工具
├── config #配置文件
├── controller #控制器
├── daos   #数据库访问层
├── logs   #日志目录
├── middleware  #中间件目录
├── socket #socketio目录
├── app.js #入口文件
└── router.js #路由               

入口文件app.js

主要就是几个中间件配置需要注意一下,这里同时还加载了 socket.io 服务。socket.io 相关的基本知识点可以看我之前写的文章关于socket.io的使用。

//app.js
//...
const path = require("path");
const baseDir = path.normalize(__dirname + "/..");// gzip
app.use(compress({filter: function(content_type) {return /text|javascript/i.test(content_type);},threshold: 2048,flush: require("zlib").Z_SYNC_FLUSH})
);// 解析请求
app.use(koaBody({jsonLimit: 1024 * 1024 * 5,formLimit: 1024 * 1024 * 5,textLimit: 1024 * 1024 * 5,multipart: true, // 解析FormData数据formidable: { uploadDir: path.join(baseDir, "public/upload") }//上传文件目录})
);// 设置静态目录
app.use(static(path.join(baseDir, "public"), { index: false }));
app.use(favicon(path.join(baseDir, "public/favicon.ico")));//cors
app.use(cors({origin: "http://localhost:" + config.clientPort,credentials: true,allowMethods: ["GET", "POST", "DELETE"],exposeHeaders: ["Authorization"],allowHeaders: ["Content-Type", "Authorization", "Accept"]})
);//json-web-token中间件
app.use(jwt({secret: config.secret,exp: config.exp})
);// 登录验证中间件,exclude 表示不验证的页面,include 表示要验证的页面
app.use(verify({exclude: ["/login", "/register", "/search"]})
);// 错误处理中间件
app.use(errorHandler()); // 路由
addRouters(router);
app.use(router.routes()).use(router.allowedMethods());// 处理404
app.use(async (ctx, next) => {log.error(`404 ${ctx.message} : ${ctx.href}`);ctx.status = 404;ctx.body = { code: 404, message: "404! not found !" };
});// 处理中间件和系统错误
app.on("error", (err, ctx) => {log.error(err); //log all errorsctx.status = 500;ctx.statusText = "Internal Server Error";if (ctx.app.env === "development") {//throw the error to frontEnd when in the develop modectx.res.end(err.stack); //finish the response} else {ctx.body = { code: -1, message: "Server Error" };}
});if (!module.parent) {const { port, socketPort } = config;/*** koa app*/app.listen(port);log.info(`=== app server running on port ${port}===`);console.log("app server running at: http://localhost:%d", port);/*** socket.io*/addSocket(io);server.listen(socketPort);
}

跨域cors 和 json web token

这里解释一下 koa-cors 参数的设置,我项目使用的是 json web token,需要把认证字段Authorization添加到header,前端获取该header字段,之后给后台发送http请求的时候,再带上该Authorization。

  • origin:如果要访问header里面的字段或者设置cookie,要写具体的域名地址,用 星号 * 是不行的;
  • credentials:主要是给前端获取cookie;
  • allowMethods:允许访问的方法;
  • exposeHeaders:前端如果要获取该header字段,必须写明(json web token用);
  • allowHeaders:添加到header的字段;

至于 json web token的原理,网上资料齐全,这里不再介绍了。

app.use(cors({origin: "http://localhost:" + config.clientPort, // 访问header,要写明具体域名才行credentials: true, //将凭证暴露出来, 前端才能获取cookieallowMethods: ["GET", "POST", "DELETE"],exposeHeaders: ["Authorization"], // 将header字段expose出去allowHeaders: ["Content-Type", "Authorization", "Accept"] // 允许添加到header的字段})
);

中间件middleware

koa 的中间件就是 web开发的利器,通过它可以非常方便的实现 强类型语言中的 aop 切面编程,而koa2 中间件 的编写也足够简单 koajs。

项目在以下几个地方都用中间件进行了封装,很多重复的样板代码因此得以简化。

  • json web token(jwt)
  • 登录验证(verify)
  • 错误处理(errorHandler)

就以最简单的错误处理中间件为例子,如果不使用错误处理中间件,我们需要每个控制器方法进行 try{…} catch{…} ,其他中间件编写方式类似,就不再介绍。

/*** error handler 中间件*/
module.exports = () => {return async (ctx, next) => {try {await next();//没有错误则进入下一个中间件} catch (err) {log.error(err);let obj = {code: -1,message: '服务器错误'};if (ctx.app.env === 'development') {obj.err = err;}ctx.body = obj}};
};// 控制器代码使用error handler中间件后,每个方法都不需要 try catch处理错误,记录错误日志,处理逻辑都集中在中间件里面了。
exports.getInfo = async function(ctx) {// try {const token = await ctx.verify();const [users, friends] = await Promise.all([userDao.getUser({ id: token.uid }),getFriends([token.uid])]);const msgs = applys.map(formatTime);ctx.body = {code: 0,message: "好友列表",data: {user: users[0],friends: mergeReads(friends, reads),groups,msgs}};// } catch (err) {//     log.error(err);//     let obj = {//         code: -1,//         message: "服务器错误"//     };//     if (ctx.app.env === "development") {//         obj.err = err;//     }//     ctx.body = obj;// }
};

路由配置

路由配置只使用了get,post 方法,当然要使用 put,delete也只是改一下名字就行。

// router.js
const { uploadFile } = require('./controller/file')
const { login, register } = require('./controller/sign')
const { addGroup, delGroup, updateGroup } = require('./controller/group')
//...module.exports = function (router) {router.post('/login', login).post('/register', register).post('/upload', uploadFile).post('/addgroup', addGroup).post('/delgroup', delGroup).post('/updategroup', updateGroup)//...
};

控制器

以updateInfo方法为例,koa2 已经全面支持 async await,编写方式和同步代码没多大区别。

exports.updateInfo = async function (ctx) {const form = ctx.request.body;const token = await ctx.verify();const ret = await userDao.update([form, token.uid]);if (!ret.affectedRows) {return ctx.body = {code: 2,message: '更新失败'};}ctx.body = {code: 0,message: '更新成功'};
}

后续

接着下一编就是基于 mysql 构建 数据库访问层。

转载于:https://www.cnblogs.com/edwardloveyou/p/10673663.html

koa+mysql+vue+socket.io全栈开发之web api篇相关推荐

  1. 利用dao传值给mysql_koa+mysql+vue+socket.io全栈开发之数据访问篇

    后端搭起大体的框架后,接着涉及到的就是如何将数据持久化的问题,也就是对数据库进行 CURD 操作. 关于数据库方案, mongodb 和 mysql 都使用过,但我选用的是 mysql,原因: 目前为 ...

  2. Python全栈开发之MySQL

    No.1 数据库概念 什么是数据库? 数据库就是一种特殊的文件,内部存储着需要的数据 RDBMS 所谓关系数据库,是建立在关系模型基础的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据 SQ ...

  3. 【线上峰会】如何一天掌握物联网全栈开发之道

    当移动红利时代结束,人才需求接近饱和的同时,传感技术.云计算.大数据.人工智能的日益成熟,并与智能家居.智慧城市相融合,将我们带入了真正智能化的物联网时代.那么,作为开发者的我们,又该如何顺势而为? ...

  4. 战争热诚的python全栈开发之路

    战争热诚的python全栈开发之路 从学习python开始,一直是自己摸索,但是时间不等人啊,所以自己为了节省时间,决定报个班系统学习,下面整理的文章都是自己学习后,认为重要的需要弄懂的知识点,做出链 ...

  5. python全栈开发要学些什么_战争热诚的python全栈开发之路

    从学习python开始,一直是自己摸索,但是时间不等人啊,所以自己为了节省时间,决定报个班系统学习,下面整理的文章都是自己学习后,认为重要的需要弄懂的知识点,做出链接,一方面是为了自己找的话方便,一方 ...

  6. Python全栈开发之11、进程和线程

    一.线程 多任务可以由多进程完成,也可以由一个进程内的多线程完成,一个进程内的所有线程,共享同一块内存python中创建线程比较简单,导入threading模块,下面来看一下代码中如何创建多线程. d ...

  7. Python全栈开发之Django基础

    No.1 MVC&MTV MVC M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增.删.改.查操作 V全拼为View,用于封装结果,生成页面展示的html内容 C全拼为Co ...

  8. Python全栈开发之路day1

    目录 计算机介绍 计算机硬件组成 计算机基本原理 发展趋势 计算机上面常用的计算单位(容量,速度等) 字符编码  计算机介绍 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以 ...

  9. python 全栈开发之路

    本节内容 计算机发展介绍 计算机硬件组成 计算机基本原理 计算机 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能.是能够 ...

最新文章

  1. 去掉[]中的英文(正则表达式)C#
  2. 雾霾经济:这10款产品,马云看了都想投资
  3. CMake 入门与进阶
  4. python中提取pdf文件某些页_人工智能|Python提取PDF中的文本并朗读
  5. 在服务器托管中asp***的防范注意些什么?
  6. eBPF学习记录(四)使用libbpf开发eBPF程序
  7. js导出的xlsx无法打开_遇到U盘无法打开,属性显示0字节这样的问题?数据该如何导出?...
  8. mysql五日均线代码_通达信均线源码,5日通达信均线公式源码
  9. eclipse 安装windows builder的问题及解决办法
  10. DWORD WINAPI
  11. “以图搜图”引擎及网站合集
  12. 参与流片是一种怎样的体验
  13. 根据图片地址上传图片
  14. 云联惠创业经营者认证_广州公安打掉云联惠涉传销组织 零壹财经曾发文警示...
  15. php eval 引号,PHP手册-eval()(可以将单引号中的变量解析)
  16. 选择时间检定仪应该注意这11点
  17. 深度解析——图片加载到内存中的大小计算内存优化
  18. Kubernetes Pod Evicted
  19. ubuntu 挂载文件后,文件权限属于root,只能读不能写解决办法
  20. ps教程-双重曝光效果实现

热门文章

  1. AC日记——友好城市 洛谷 P2782
  2. python 学习笔记8 (模块)
  3. 恼人的函数指针(二)
  4. BestCoder冠军赛 - 1005 Game 【DP】
  5. R—计算系统发育多样性PD (Calculate Faith’s Phylogenetic Diversity)
  6. java编写十个评委_Java题 在歌星大奖赛中,有10个评委为参赛的选手打分,分数为1~100分。选手最后得分...
  7. matlab在图像上画出来的矩形框如何变成可托动的_计算机基础系列:源代码如何被计算机执行...
  8. like mysql 相反_mysql真的不能做搜索引擎吗?
  9. android ios 上传图片到服务器,.net 接收ios, android的上传图片
  10. unity3d api 中文文档_接口文档系统-showdoc安装部署