Koa2 从入门到精通二
MySQL
- 安装
npm install mysql -S - 我本地数据库配置
{
host: 'localhost',
user: 'root',
password: '',
database: 'demo'
}
- 创建测试数据库,database: demo 和 users用户表
- 数据库连接配置
conf/db.js,在项目目录下创建conf文件夹,用来做数据连接的配置或其他配置
// 数据库连接配置
const env = process.env.NODE_ENV; // 环境参数
// 配置
let MYSQL_CONF
// 开发环境
if (env === 'dev') {
// 配置mysql
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '',
database: 'demo'
}
}
// 线上环境
if (env === 'production') {
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '',
database: 'myblog'
}
}
module.exports = {
MYSQL_CONF
}
- 数据库连接以及数据库操作统一定义
在项目目录下创建db文件夹
const mysql = require('mysql');
const {
MYSQL_CONF
} = require('./../conf/db.js');
// 创建链接对象
const con = mysql.createConnection(MYSQL_CONF)
// 开始链接
con.connect()
// 统一执行 sql 的函数
function exec(sql) {
const promise = new Promise((resolve, reject) => {
con.query(sql, (err, result) => {
if (err) {
reject(err);
return
}
resolve(result);
})
})
return promise
}
module.exports = {
exec,
escape: mysql.escape
}
- 测试数据库能否连接成功,虽然没有数据,但结果显示正常
- 数据库操作安全性问题
mysql.escape() 特殊字符转义
xss 预防xss攻击
npm install xss -S
md5密码加密 在项目下创建 utils 文件作为工具类
const crypto = require('crypto')
// 密钥
const SECRET_KEY = 'ax_d_milo_280383404.wtf!ob987536j*%1jg-_+ab2'
// md5加密
function md5(content) {
let md5 = crypto.createHash('md5')
return md5.update(content).digest('hex')
}
// 加密函数
function genPassword(password) {
const str = `password=${password}&key=${SECRET_KEY}`
return md5(str)
}
module.exports = {
genPassword
}
- 定义控制器,用来对数据库进一步操作
const {
exec,
escape
} = require('../db/mysql')
// 用于md5加密
const { genPassword } = require('./../utils/cryp')
// 预防xss攻击
const xss = require('xss')
// 检查用户是否已经注册
const checkIsRegister = async (username) => {
username = escape(username)
username = xss(username)
const sql = `
SELECT * from users WHERE username=${username}
`
const result = await exec(sql)
if (result.length) {
// 表示该用户已经注册
return true
}
return false
}
// 注册
const register = async (name, username, password) => {
name = xss(escape(name))
username = xss(escape(username))
password = genPassword(password)
const sql = `
INSERT INTO users (name, username, password)
VALUES (${name}, ${username}, '${password}')
`
const result = await exec(sql)
return {
id: result.insertId
}
}
module.exports = {
checkIsRegister,
register
}
- 路由,调用控制器定义的函数,对数据库进行操作,并返回结果
const router = require('koa-router')()
const { checkIsRegister, register } = require('./../controller/users')
router.prefix('/users')
router.post('/register', async function (ctx, next) {
const { name, username, password } = ctx.request.body
const isRegister = await checkIsRegister(username)
if (isRegister) {
ctx.body = "该用户已被注册"
} else {
const registerResult = await register(name, username, password)
ctx.body = registerResult
}
})
module.exports = router
- 自定义数据模型,对返回结果的格式进行统一
// 数据模型
class BaseModel {
constructor(data, message) {
if (typeof data === 'string') {
this.message = data;
data = null;
message = null;
}
if (data) {
this.data = data;
}
if (message) {
this.message = message;
}
}
}
// 成功
class SuccessModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.status = 0;
}
}
// 失败
class ErrorModel extends BaseModel {
constructor(data, message) {
super(data, message);
this.status = -1;
}
}
module.exports = {
SuccessModel,
ErrorModel
}
const router = require('koa-router')()
const { checkIsRegister, register } = require('./../controller/users')
const { SuccessModel, ErrorModel } = require('./../model/resModel')
router.prefix('/users')
router.post('/register', async function (ctx, next) {
try {
const { name, username, password } = ctx.request.body
const isRegister = await checkIsRegister(username)
if (isRegister) {
ctx.body = new ErrorModel('该用户已被注册')
} else {
const registerResult = await register(name, username, password)
ctx.body = new SuccessModel(registerResult, '注册成功')
}
}catch {
ctx.body = new ErrorModel('注册失败')
}
})
module.exports = router
koa-morgan 进行线上环境日志记录
- 参考文档
- 安装
npm install koa-morgan -S - 使用,在项目文件下新建logs文件夹
const morgan = require('koa-morgan')
const path = require('path')
const fs = require('fs')
// 开发环境日志记录,生成环境直接在控制台输出
const ENV = process.env.NODE_ENV
if (ENV === 'dev') {
// dev
app.use(morgan('dev'))
} else {
// production
const logFileName = path.join(__dirname, 'logs', 'access.log')
const writeStream = fs.createWriteStream(logFileName, {
flags: 'a'
})
app.use(morgan('combined', {
stream: writeStream
}));
}
- 去掉koa-logger
npm uninstall koa-logger
const Koa = require('koa')
const app = new Koa()
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const morgan = require('koa-morgan')
const path = require('path')
const fs = require('fs')
const index = require('./routes/index')
const users = require('./routes/users')
// error handler
onerror(app)
// middlewares
app.use(bodyparser({
enableTypes:['json', 'form', 'text']
}))
app.use(json())
app.use(require('koa-static')(__dirname + '/public/'))
// production into logs,dev console.log
const ENV = process.env.NODE_ENV
if (ENV === 'dev') {
// dev
app.use(morgan('dev'))
} else {
// production
const logFileName = path.join(__dirname, 'logs', 'access.log')
const writeStream = fs.createWriteStream(logFileName, {
flags: 'a'
})
app.use(morgan('combined', {
stream: writeStream
}));
}
// routes
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
module.exports = app