Koa2 & mySQL & PM2 搭建后端服务

3,903 阅读8分钟

嘘!啰嗦一句话。

作为一名前端开发工程师,我们平常和后端接触最多的就是接口的对接。那么后端同事是怎么写一个接口来给到我们前端的同学去获取数据库数据并做一些花里胡哨的功能呢?今天我们就用Koa2 & mySql来搭建一个后端服务器,实现自己写api的中国梦!


前言

对于部分前端开发的小伙伴来说,后端开发可能是一个陌生的领域,毕竟现在前端的工作繁重(我哪有时间去学习后端开发鸭!)。幸好有了Node.js这个利器,让我们可以在现有的前端技能基础上去实现一些后端的技术,这也降低了我们入门后端开发的门槛。

今天给大家介绍的这个小可(dong)爱(xi)就是我通过最近一个项目(这个项目是由koa2+mysql + pm2作为后端服务)中抽离出来的一套Koa2 & MySQL & PM2基础模板。目的就是让我们的前端小伙伴可以直接使用它去开发接口,实现自己的梦想。

代码仓库github.com/yigeyi/funn…

教程目前考虑在windows环境下使用pm2来启动服务,且已dev环境进行测试


目标

通过这一套基础模板,快速开发api,实现前端后端自我完成。也就是说,你把代码克隆下来之后,以学习为目的的话,你只需要开始写api就行了,一些简单的配置我都配置好了,你只要按照以下步骤去操作,便可以自己写api,自己对接接口,然后就自己怼自己了。


使用技术

  • Koa2
  • MySql(请确保你的windows已经安装了mysql,并且可以正常启动mysql
  • PM2 (请确保你的windows已经安装了PM2,并且可以正常启动PM2


软件安装教程

  • MySql安装:blog.csdn.net/weixin_4343…
    • 安装wamp或者phpstudy这两个神器就会自动帮你安装MySql,基本上就满足你的学习开发了,如果你是要在生产环境使用的话,我相信你的环境已经具备所需的软件了
  • PM2安装:juejin.cn/post/684490…
    • 上面PM2教程是我上一次写的一篇文章(写的有点烂,我都看不下去了,哈哈,不过pm2的安装非常的容易,大家可以看看,再不然也可以百度找一下相关完整的教程)


代码结构



环境配置

使用这一套Koa2 & MySQL & PM2基础模板之前,你需要确保你的电脑安装了node、mysql、PM2 


克隆代码

git地址:https://github.com/yigeyi/funnyProject.git


创建数据库

代码文件中我提供了mysql建表的sql语句,你需要在你的电脑中先创建一个名为dev_db的数据库,创建之后执行代码文件中的dev_db.sql文件即可


代码安装

npm i    //就这样子,先把node繁重的node_module安装下来,嘿嘿

//如果npm不行,那就试一下 cnpm i


启动服务

使用pm2 start pm2.config.js --only dev 来启动koa2项目,当出现下面截图一样内容的时候,证明你的koa2项目已经正确启动了。


这个时候你可以使用http://localhost:3200进行访问项目(关于3200端口配置,我会在下面进行解释)


配置说明

项目的主要运行流程为:通过pm2 start pm2.config.js --only dev/prod/test启动项目之后(也可以使用npm run dev/prod/test),koa2会通过当前启动的环境来配置不同的config参数(app.js引入配置文件),从而使用不同的端口以及mysql参数配置(配置在config文件夹中,下面详细说)


app.js配置引入

const Koa = require('koa')

const app = new Koa() 
const env = process.env.NODE_ENV;
const config = require('./config')
const router = require('./app/router')
...
/*更多的配置可以拉取仓库代码进行查看*/


启动环境配置

PM2配置:pm2.config.js

let startFile = "./app.js"
module.exports = {
  apps: [{
    name: "prod",
    script: startFile,
    env: {
      "NODE_ENV": "production"
    }
  }, {
    // 测试环境
    name: "test",
    script: startFile,
    env: {
      "NODE_ENV": "test"
    }
  }, {
    // 开发环境
    name: "dev",
    script: startFile,
    env: {
      "NODE_ENV": "development"
    }
  }
  ]
}


环境参数配置: /conf/config.*.js


/*conf.dev.js*/
const conf = {
  port: 3200, //启动端口 ,这个根据你电脑环境的实际情况来配置
  base_url: '',// 当前api服务器的域名
  mysql: { // mysql数据库信息
    host: 'localhost',
    port: '3306',
    database: 'dev_db',  //你可以修改你的数据库名字
    user: 'root',  //数据库登录账户 你寄己来
    password: '', //数据库登录密码 我就不知道你的是啥啦
    charset: 'UTF8mb4'
  }
}
module.exports = conf;

通过配置不同的config后,当我们通过pm2 start pm2.config.js --only dev/prod/testkoa会根据我们在pm2.config.js中配置的NODE_ENV来确定当前是什么运行环境,并通过/config/index.js中来使用不同的配置端口以及参数


数据库配置

配置文件路径:/db/mysql.js

const db = require("mysql");
const config = require('../config').mysql;
const client = function () {}
var pool = db.createPool({
  host: config.host,
  port: config.port,
  user: config.user,
  password: config.password,
  database: config.database,
  charset: 'UTF8mb4'
});


路由配置

路由配置:/router/index.js

/*router/index.js*/
const router = require('koa-router')()
let app = require('./v1.js')
//接口映射
router.use('/api/app', app.routes(), app.allowedMethods())
// vue history 设置
router.get('*', async(ctx, next)=>{
  return await ctx.render('index', {})
})
//返回注册路由
module.exports = router


数据库模型(Model)创建

Model主要是告诉sequelize如何映射数据库表,
sequelize.define(modelName, attributes, [options]) -> Modal这个实例方法用于定义一个新的model模型)。model相当于数据库中的表,该对象不能通过构造函数实例化,而只能通过sequelize.define()或者sequelize.import()方法创建
第二个参数是指定列名和数据类型,如果是主键,需要更加详细的指定。第三个参数是额外的配置

具体的sequelize配置以使用可以参考中文文档进行学习

//eg:
/*models\sequelize-model\test.js*/
module.exports = function(sequelize, DataTypes) {
  return sequelize.define('test', {
    id: {
      type: DataTypes.INTEGER(11).UNSIGNED,
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    nick_name: {
      type: DataTypes.INTEGER(11),
      allowNull: false
    },
  }, {
    tableName: 'test',
    timestamps: false
  });
};

Model中写的代码其实就是和我们在mysql中编写的表结构一样的,只不过是通过不同的语言来进行表达而已,也就是你如果在mysql中新增表或者字段,那么你也需要在相对应的model中去更新相关的字段。也有插件(中间件)可以自动映射数据库表结构到模型中,但是第一次使用发现有点小问题,所以我就没使用了。

/*mysql 创建表结构*/
CREATE TABLE `test` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`nick_name` VARCHAR(50) NULL DEFAULT '',
	PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=5
;



写接口啦!

接口编写完成,当我们访问接口的时候会在 /router/v1中找到对应的路由名字,接着访问我们对应的控制器接口地址,进行业务的处理
router/v1 统一包装接口映射

/*router/v1*/
//业务接口
const router = require('koa-router')()
// 引入不同控制器接口文件
// 根据不同的业务模块我们可以创建不同的controller,我们可以把相同模块的接口写在相同的controller中,并通过此处进行引入,例如 test1
const test = require('../controller/test')
const test1 = require('../controller/test1') 
const test2 = require('../controller/test2') 

//接口映射
//接口访问地址http://localhost:port/api/app/test
///api/app这一段已经在index.js中配置了前缀,所以在写接口的时候需要加上api/app/
//controller
router.post('/test',test.getTest)
router.post('/createData',test.createData)
//controller1
router.post('/test1',test1.getTest)
//controller和service分离部分
router.post('/test2',test2.getTest)
module.exports = router


控制器:controller/*.js

/*controller/test.js*/
const models = require('../models')
const {
  joi,
  validateParams
} = require('../base/controller.js')
module.exports = {
  //获取数据库数据
  async getTest(ctx){
    let data = {
      tip: '你安装了数据库就可以把上面注释打开'
    }
    return ctx.output({data:data},'获取成功',0)
  },
  async createData(ctx){
    //参数验证
    //通过获取post传递过来的参数
    //再使用模型把数据插入数据库
    const schema = joi.object().keys({
      nick_name: joi.string().required()
    })
    validateParams(ctx.input, schema)
    let nick_name = ctx.input.nick_name
    let parmas = {
      nick_name: nick_name
    }
    let res = await models.test.create(parmas)
    if(res){
      return ctx.output({},'添加成功',0)
    }
    // let data = {
    //   tip: '你安装了数据库就可以把上面注释打开'
    // }
    // return ctx.output({data:data},'获取成功',0)
  }
}


截止目前,通过上面的一系列配置以及代码的cv之后,我们就可以通过postman来测试接口是否成功啦!


控制器controller和service层分离

当我们业务比较复杂的时候,我们并不希望处理数据库的逻辑和我们的普通业务逻辑放在一起,这个时候我们可以把处理数据库的操作分离出来放在一个service层,然后控制器controller就只是处理我们的业务逻辑

具体操作:通过新增service文件夹,再从文件夹中新建不同的service模块文件,例如serviceTest2.js,同时把test2中和数据库操作相关的操作抽离到serviceTest2.js中,这样子我们就可以清晰知道我们各个业务层所做的事情,也方便我们进行维护。

/*app\controller\test2.js*/
//这个文件演示 控制器和service层分离
const serviceTest = require('../service/v1/serviceTest2.js')
module.exports = {
  //获取数据库数据
  async getTest(ctx){
    let res = await serviceTest.getTest()
    return ctx.output({data:res},'获取成功',0)
  }
}

/*app\service\v1\serviceTest2.js*/
const models = require('../../models')
module.exports = {
  //获取数据库数据
  async getTest(ctx){
    let res = await models.test.findOne({
      where: {
        id: 1
      }
    })
    let data = {
      name: res.dataValues.nick_name
    }
    // let data = {
    //   tip: '这里从控制器抽离出来的操作数据库的东西,你如果安装了mysql,可以打开上面的注释'
    // }
    return data
  }
}

PM2更多操作

pm2 restart pm2.config.js --only dev/prop/test  //重启服务
pm2 log // 查看日志
pm2 kill //杀死进程

官方文档:https://pm2.keymetrics.io/docs/usage/quick-start/


写在最后

  • 以上文章便是我在这两天在一个koa2项目中抽离出来的一套代码模板,大家只要把代码克隆下来并保证电脑上已经安装了所需软件,并可以进行koa2项目的启动和编写api了。
  • 这是一篇入门级别的简单分享文章,如有哪里有错误,希望您可以帮忙提出纠正,非常感谢。
  • 如果你觉得还可以的话,希望您可以给我一个星星哦十分感谢