本人弄了一个koa脚手架,koa和mongodb组合而成, 已上传GitHub. 👏 👏 👏 👏
传送门
目录结构如上,一个控制器(也就是写代码的地方),一个日志,一个数据库模型,一个路由,一个工具,和入口文件。写代码只要添加路由 填充控制器就好了,如图所示
下面解析下有哪些构成的👇
const Koa = require('koa'); const app = new Koa(); // response app.use(ctx => { ctx.body = 'Hello Koa'; }); app.listen(3000); 复制代码
更多见阮一峰koa框架
var Koa = require('koa'); var Router = require('koa-router'); var app = new Koa(); var router = new Router(); router.get('/', (ctx, next) => { // ctx.router available }); app .use(router.routes()) .use(router.allowedMethods()); 复制代码
// routers/index.js const Router = require('koa-router') const dateNumberController = require('../controllers/date_number') const router = new Router({ prefix: '/api' }) dateNumberController.prefix ='date_number' router .post(dateNumberController.getPath('add'), dateNumberController.add) .get(dateNumberController.getPath(`select`), dateNumberController.find) .post(dateNumberController.getPath(`remove`), dateNumberController.delect) .post(dateNumberController.getPath(`update`), dateNumberController.update) module.exports = router // main.js const router = require('./routers') app.use(router.routes()); 复制代码
更多详情见koa-router github
有了路由,但是我们还需要前端传递过来的参数,所以需要先获取参数
app.use(async ctx => { ctx.body = ctx.request.body; }); 复制代码
这时候post请求就可以解析了,不管是application/json
还是application/x-www-form-urlencoded
效果
更新详情见bodyparser GitHub
拿到参数后我们需要校验它
// main.js const parameter = require("koa-parameter") const error = require("koa-json-error") app.use(parameter(app)); // 这个是json错误处理,可以自动抛出http status 422 app.use( error({ postFormat: (e, { stack, ...rest }) => ({ stack, rest }) }) ) // ctx里面,比如路由里面 ctx.verifyParams({ date: { type: "string", required: true }, list: { type: "array", required: true }, }) 复制代码
拿到参数,我们下一步就是需要操作数据了
安装mongodb,然后npm安装mongoose
, 如下初始化即可
const mongoose = require('mongoose') // db是数据库名称哦,没有的话会自动创建 const DB_ADDRESS = "mongodb://localhost:27017/db" mongoose.connect(DB_ADDRESS, {useNewUrlParser: true, useUnifiedTopology: true}, err => { if (err) { log.fatal({msg: '[Mongoose] database connect failed!', err}) } else { console.log('[Mongoose] database connect success!') } }) module.exports = mongoose 复制代码
使用的时候,我们需要先建立集合(在mysql里面叫表),但是MD更灵活,可以直接在代码里面操作,我们先建立模型。
const mongoose = require('mongoose'); const { Schema, model } = mongoose; // 数据模型 let DateNumberSchema = new Schema({ date: { type: String, required: true, unique: true }, list: { type: Array, require: true }, }); module.exports = model('DateNumber', DateNumberSchema); 复制代码
查
const data = await DateNumber.find() 复制代码
新增
// 要和模型对应 const data = await to( new DateNumber({date, list}).save() 复制代码
删
const data = await DateNumber.deleteOne({date: date}) 复制代码
改
const data = await DateNumber.updateOne({date}, {$set: {list}}) 复制代码
例子
const DateNumber = require('../models/dateNumber') class DateNumberController { prefix = '' getPath(name){ return `/${this.prefix}/${name}` } async add(ctx, next){ ctx.verifyParams({ date: { type: "string", required: true }, list: { type: "array", required: true }, }) const {date, list} = ctx.request.body const [err, data] = await to( new DateNumber({date, list}).save() ) if(err) return ctx.throw(500, err) ctx.response.body = data } async find(ctx, next){ const data = await DateNumber.find() ctx.response.body = data.join('\n') log.info('find') } async delect (ctx, next){ ctx.verifyParams({ date: { type: "string", required: true }, }) const {date} = ctx.request.body const data = await DateNumber.deleteOne({date: date}) ctx.response.body = data } async update(ctx, next){ ctx.verifyParams({ date: { type: "string", required: true }, list: { type: "array", required: true }, }) const {date, list} = ctx.request.body const [err, data] = await to( DateNumber.updateOne({date}, {$set: {list}}) ) if(err) return ctx.throw(500, err) ctx.response.body = data } } module.exports = new DateNumberController() 复制代码
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table | joins | 表连接,MongoDB不支持 |
primary | key | primary key 主键,MongoDB自动将_id字段设置为主键 |
MAC的需要先运行mongod,然后再开一个窗口,不然会提醒找不到服务; Windows有自带的可视化软件,安装的时候install mongoDB compass勾上即可
上面有一个代码用到了to
to是对promise的一个封装,变成[err, data] 这种形式,这样有一个好处是不需要写try catch,又可以平级处理错误。
to是全局的,在main.js引入
mongodb更多见菜鸟教程
使用log4js
实现日志
使用方式
var log4js = require('log4js'); var logger = log4js.getLogger(); logger.level = 'debug'; logger.debug("Some debug messages"); 复制代码
等级作用是,输出>=当前级别的日志
我设置的是,info正常输出,输出的时候按日期分(这样文件不会太大),如果遇到error这种大问题就发邮件,例子如下,包含测试代码,你配置下email里面的账号密码就可以运行了
const config = { // 例子 email: { host: 'smtp.qq.com', auth: { user: '你的qq号@qq.com', pass: '你的密码,', }, recipients: '发送方@126.com' } } const LOGINFO = { appenders: { info: { type: "DateFile", category: 'dateFileLog', filename: path.join(__dirname, './log/info/'), pattern: "yyyy-MM-dd.log", alwaysIncludePattern: true }, email: { type: '@log4js-node/smtp', //发送邮件的邮箱 sender: config.email.auth.user, //标题 subject: 'Latest error report', SMTP: { host: config.email.host, auth: config.email.auth, }, recipients: config.email.recipients } }, } const log4js = require('log4js') log4js.configure(LOGINFO) const log_info = log4js.getLogger() const log_error = log4js.getLogger('error') global.log = { debug: log_info.debug.bind(log_info), info: log_info.info.bind(log_info), warn: log_info.warn.bind(log_info), error: log_error.error.bind(log_error), fatal: log_error.fatal.bind(log_error), } // 这个是测试代码 setTimeout(() => { log.fatal({ msg: '测试', err: 'fatal' }) }, 400) 复制代码
邮箱密钥获取方式: 进入qq邮箱,设置----> 账户 ------->开启服务:POP3/SMTP服务 ----->生成授权码
log.fatal({ msg: '测试', err: 'fatal' }) 复制代码
效果
log4js更多详情见 log4js github
log4js邮箱更多详情见 log4js-node/smtp github
各位大哥哥小姐姐麻烦点个赞,我要冲3级,谢谢
-- 完 --