为什么选择Koa

koa是Express框架同个公司的产品,是开发者在node7.0版本之后使用promise的api把express再次封装了一次,起名Koa,Koa=Express+Promise,并且中间件的使用由链型变成了环形【洋葱】

官网

网友笔记

安装

cnpm i koa --save

最基础使用

const Koa = require('koa');
const app = new Koa();
app.listen(3000);

中间件middleware

处在 HTTP Request 和 HTTP Response 中间,用来实现某种中间功能的函数,就叫做"中间件",每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next函数。只要调用next函数,就可以把执行权转交给下一个中间件

我们需要的中间件有

  • koa-body 处理post请求
  • koa-router 智能处理路由
  • koa2-cors 跨域
  • mongoose 连接数据库
  • log4js 日记记录插件
  • module-alias 路径引用,避免非常长的相对路径

其他中间件有,因为使用前后端分离所以用不到

  • koa-staic ,静态文件访问
  • koa-view ,服务器渲染的插件
  • koa-session ,koa内置了cookie方法,只需要下载session

我的目录建议

  • 一个入口文件叫app.js或者叫server.js
  • 一个config.js放置一些全局的配置
  • 一个api文件夹放我的路由
  • 一个request文件夹放我的请求
  • 一个router文件夹放路由配置入口
  • 一个utils文件夹放一些时间处理,uuid的插件js
  • 一个mongoose文件夹放数据库的连接入口,里面再建一个model文件夹
  • 一个middleware文件夹放自己的中间件

上代码

需要先把上面的中间件安装了

// app.js 入口文件

const Koa = require('koa')
const koaBody = require('koa-body');
const cors = require('koa2-cors')
const config = require('./src/config')
const router = require('./src/router')
//启动的时候连接一下mongodb,不需要use
const mongoose = require('./src/mongoose')
// 自定义中间件
const whiteList = require('./src/middleware/whiteList') const app = new Koa()
app.use(whiteList()); //白名单放第一位
app.use(koaBody({
formLimit:10000 * 1024 * 1024, //JSON 数据体的大小限制,默认56k
textLimit:10000 * 1024 * 1024, //限制表单请求体的大小,默认56k
jsonLimit:10000 * 1024 * 1024, //限制 text body 的大小,默认56k
multipart: true,
formidable: {
maxFileSize: 2000 * 1024 * 1024 // 设置上传文件大小最大限制,默认2M
}
}));
app.use(xmlParse());
app.use(cors()); //放到route前面,跨域
app.use(router.routes());
app.use(router.allowedMethods()); app.listen(config.port)
console.log('server start at port:', config.port)
// config.js

module.exports = {
port: 3000,
filePath:'E:\\nginx-1.16.1\\html\\uploadFile\\', //开发环境
// filePath:'/usr/local/nginx/html/uploadFile/', //正式环境
fileUrl : "http://localhost/uploadFile/", //开发环境
// fileUrl : "http://47.97.201.201/uploadFile/", //正式环境
// 白名单
whiteList:[
"127.0.0.1:8848",
"127.0.0.1:8080"
]
}
// router/index.js

const Router = require('koa-router')
const router = new Router() router.get('/get', api.get)
router.post('/post', api.post)
router.post('/uploadFile', api.uploadFile)
router.post('/uploadFiles', api.uploadFiles)
router.post('/uploadBase64', api.uploadBase64) module.exports = router
// api/index.js

const upload = require('../util/upload')

exports.get  = async (ctx, next) => {
get方式的取query的值
let query = ctx.request.query;
await next();
ctx.body = query; //返回值
}
exports.post = async (ctx, next) => {
//post取body的值
let body = ctx.request.body;
await next();
ctx.body = body; //返回值
}
exports.uploadFile = async (ctx, next) => {
let body = ctx.request.body;
var res = await upload.uploadFile(ctx)
await next();
ctx.body = {file:res}; //返回值
}
exports.uploadBase64 = async (ctx, next) => {
let body = ctx.request.body;
var res = await upload.uploadBase64(body.file,body.fileName)
await next();
ctx.body = {file:res}; //返回值
}
// util/upload.js

const path = require("path");
const fs = require("fs");
const uuid = require('./uuid'); // 自己写一个
const config = require('../config');
let Duplex = require('stream').Duplex; exports.uploadFile = async function(ctx) {
// 上传单个文件
const file = ctx.request.files.file; // 获取上传文件
// 创建可读流
const reader = fs.createReadStream(file.path);
let fileId = uuid()
let fileName = file.name;
let newName = fileId + "_" + fileName;
let filePath = config.filePath + `${newName}`;
// 创建可写流
const stream = fs.createWriteStream(filePath);
// 可读流通过管道写入可写流
reader.pipe(stream);
return {fileId,fileName,newName,fileUrl:config.fileUrl,url:filePath};
} exports.uploadBase64 = async function(file,fileName) {
// 上传单个base64
// 创建可读流
var base64 = file.replace(/^data:.+;base64,/,"");
var buffer = Buffer.from(base64, 'base64');
let fileId = uuid()
let newName = fileId + "_" + fileName;
let filePath = config.filePath + `${newName}`;
let reader = new Duplex();
reader.push(buffer);
reader.push(null);
const stream = fs.createWriteStream(filePath);
// 可读流通过管道写入可写流
reader.pipe(stream);
return {fileId,fileName,newName,fileUrl:config.fileUrl,url:filePath};
}
// mongoose/index.js

var mongoose = require('mongoose');
mongoose.set('useFindAndModify', false)
mongoose.connect('mongodb://localhost/mydb',{useNewUrlParser:true,useUnifiedTopology: true},function(err){
if(err){
console.log('Connection Error:' + err)
}else{
console.log('mongoose Connection success!')
}
}); module.exports = mongoose;
// 自定义白名单中间件
// middleware/whiteList.js const config = require('../config') module.exports = () => {
return async (ctx, next) => {
var referer = ctx.request.header.referer;
var origin = ctx.request.header.origin;
if(referer==undefined||origin==undefined){
await next() //可以再网页之外访问
}else{
let whiteList = config.whiteList;
if(whiteList.includes(origin.split("//")[1])){
await next()
}else{
ctx.body = "访问地址不在白名单内";
}
}
}
}
// utils/logger.js 

const log4js = require('log4js');
const path = require('path')
// 定义log config
log4js.configure({
appenders: {
// 定义两个输出源
info: { type: 'file', filename: path.resolve('log/info.log') },
error: { type: 'file', filename: path.resolve('log/error.log') }
},
categories: {
// 为info/warn/debug 类型log调用info输出源 error/fatal 调用error输出源
default: { appenders: ['info'], level: 'info' },
info: { appenders: ['info'], level: 'info' },
warn: { appenders: ['info'], level: 'warn' },
debug: { appenders: ['info'], level: 'debug' },
error: { appenders: ['error'], level: 'error' },
fatal: { appenders: ['error'], level: 'fatal' },
}
});
// 导出5种类型的 logger
module.exports = {
debug: (...params) => log4js.getLogger('debug').debug(...params),
info: (...params) => log4js.getLogger('info').info(...params),
warn: (...params) => log4js.getLogger('warn').warn(...params),
error: (...params) => log4js.getLogger('error').error(...params),
fatal: (...params) => log4js.getLogger('fatal').fatal(...params),
} // 使用
const logger = require('./utils/logger.js')
// 记录访问,可以自己写一个中间件
logger.info('请求url:', url , method||'get', JSON.stringify(data))

上面的代码,配置了一个能直接用Koa项目,包括了文件上传的代码,mongodb数据库连接,路由怎么写,还有白名单过滤器,mongoose的使用查看mongoose笔记,下一篇用Koa连接微信服务器

Egg

除了这两个框架外,还有一个Egg是阿里封装的,Egg的文档是这么说的,Egg 继承于 Koa,如上述,Koa 是一个非常优秀的框架,然而对于企业级应用来说,它还比较基础,而Egg选择了Koa作为其基础框架,在它的模型基础上,进一步对它进行了一些增强,我看了他的文档使用,应该是把Koa加Java的MVC模式融合再了一起,Egg=Koa+MVC,这个框架更加规范严格企业化,让每个路由都继承框架内部的Controller类和Service 类, 并且把数据库查询存到this里,随时可以调用,最优秀的是他的方法执行是用文件路径指向的,就非常像Java框架里的注解扫描了,代码如下

// app/router.js
module.exports = app => {
app.router.get('/user/:id', app.controller.user.info);
}; // app/controller/user.js
const Controller = require('egg').Controller;
class UserController extends Controller {
async info() {
const { ctx } = this;
const userId = ctx.params.id;
const userInfo = await ctx.service.user.find(userId);
ctx.body = userInfo;
}
}
module.exports = UserController; // app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {
// 默认不需要提供构造函数。
// constructor(ctx) {
// super(ctx); 如果需要在构造函数做一些处理,一定要有这句话,才能保证后面 `this.ctx`的使用。
// // 就可以直接通过 this.ctx 获取 ctx 了
// // 还可以直接通过 this.app 获取 app 了
// }
async find(uid) {
// 假如 我们拿到用户 id 从数据库获取用户详细信息
const user = await this.ctx.db.query('select * from user where uid = ?', uid); // 假定这里还有一些复杂的计算,然后返回需要的信息。
const picture = await this.getPicture(uid); return {
name: user.user_name,
age: user.age,
picture,
};
} async getPicture(uid) {
const result = await this.ctx.curl(`http://photoserver/uid=${uid}`, { dataType: 'json' });
return result.data;
}
}
module.exports = UserService; // curl http://127.0.0.1:7001/user/1234

Koa2+mongoose的更多相关文章

  1. Koa2 + Mongoose + Log4js 持久化日志

    代码地址如下:http://www.demodashi.com/demo/12466.html  之前做的项目是采用 Express 框架进行搭建的,其中的日志管理采用了 winston + Post ...

  2. koa2+mongoose搭建框架模型

    由于学的是java,所以此框架多少有点java的影子,我觉得不必排斥语言,只要思想好,所有语言均可以通用.项目分以下几层 app.js项目启动入口,类似于main函数 controller-view层 ...

  3. mongoose 操作 mongodb 笔记 (自己的笔记,自己看的)

    mongodb下载/安装 mongoose   npm install --save mongoose mongoose 数据库连接 const mongoose = require('mongoos ...

  4. koa中返回404并且刷新后才正常的解决方案

    概述 这几天学习koa2,有一些心得,记录下来,供以后开发时参考,相信对其他人也有用. 起因 这几天学习koa2,写的代码执行时有一个奇怪的bug:明明能够返回数据,却有时正常返回数据,有时偏偏给你返 ...

  5. koa2入门(3)mongoose 增删改查

    项目地址:https://github.com/caochangkui/demo/tree/koa-mongoose 连接数据库 数据库名字为:koa-mongoose const mongoose ...

  6. koa2 入门(1)koa-generator 脚手架和 mongoose 使用

    项目地址:https://github.com/caochangkui/demo/tree/koa2-learn 1 构建项目 1.1 安装koa-generator $ npm install -g ...

  7. koa2搭建服务器+使用mongoose链接mangodb

    使用node搭建服务器,用到了现在比较流行的框架koa. 1.初始化package.json npm init -y 2.安装koa2 npm i koa --save 3.搭建服务器 const K ...

  8. 手把手教你基于koa2,mongoose实现增删改查

    初始化项目 npm init -y 先安装一波乱七八糟的依赖插件(需要具备一定的koa2知识,至于mongoDB自行百度安装教程),模板引擎我使用的是art-template(据说是性能最好的,而且是 ...

  9. mongoose+koa2 按照_id更新多条数据,删除数组中的字段,然后添加新的字段,$pull和$or结合使用

    await model.photo.update({ _id: { $in: photoIdsParam } }, { $pull: { customerIds: { code: custCode, ...

随机推荐

  1. mysql字符串相关函数(并与sql server对比)

    https://blog.csdn.net/zhengxiuchen86/article/details/81220779 1.判断子串substr在字符串str中出现的位置 例子:查询']'在‘OP ...

  2. vmware fusion nat网络模式设置固定ip

    最近想在本地用虚拟环境搭一个k8s环境,但是发现虚拟机的ip会不定时自动变化,导致mosh客户端连接经常中断.于是就想让虚拟机的ip固定住,不再变动. mac 上的 vmware fusion 设置固 ...

  3. python中模块的制作

    1.import 模块名 2.from 模块名 import 类名(或方法名或全局变量) 3.from 模块名 import *   导入模块名下的所有类名,方法,全局变量 4.from 模块名 im ...

  4. spark实验(二)--scala安装(1)

    一.实验目的 (1)掌握在 Linux 虚拟机中安装 Hadoop 和 Spark 的方法: (2)熟悉 HDFS 的基本使用方法: (3)掌握使用 Spark 访问本地文件和 HDFS 文件的方法. ...

  5. 用Struts2框架报错:The Struts dispatcher cannot be found

    报错信息 The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the ...

  6. [转]轻松理解AOP思想(面向切面编程)

    原文链接 Spring是什么 先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是从功能的角度来定义的,从本质意义上来讲,S ...

  7. linux磁盘管理1-分区格式化挂载,swap,df,du,dd

    一些基础 硬盘接口类型 ide 早期家庭电脑 scsi 早期服务器 sata 目前家庭电脑 sas 目前服务器 raid卡--阵列卡 网卡绑定 ABI 应用程序与OS之间的底层接口 API 应用程序调 ...

  8. Linux centosVMware NFS介绍、NFS服务端安装配置、NFS配置选项

    一.NFS介绍 NFS是Network File System的缩写 NFS最早由Sun公司开发,分2,3,4三个版本,2和3由Sun起草开发,4.0开始Netapp公司参与并主导开发,最新为4.1版 ...

  9. C语言程序设计-现代方法(笔记3)

    第十三章 字符串 1.字符串字面量(13.1) 字符串字面量:用一对双引号括起来的字符序列.字符串字面量可以像字符常量一样包含转义字序列. 在字符串字面量中小心使用八进制和十六进制的转义序列. 字符串 ...

  10. Python爬虫教程-爬取5K分辨率超清唯美壁纸源码

    简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空,有的人喜欢美女,有的人喜欢动物.然而,终究有一天你已经产生审美疲劳了,但你下定决定要换壁纸的时候,又发现网上的壁 ...