Node.js
升级数据库
[egg官网](https://eggjs.org/zh-cn/intro/quickstart.html)
返回目录1. 快速初始化项目
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i或
$ mkdir showcase && cd showcase
$ npm init egg --type=ts
$ npm i
$ npm run dev2. 启动项目
$ npm run dev
$ open http://localhost:70013. 连接mysql数据库(使用sequelize可以跳过这一步)
- 安装对应的插件 egg-mysql :
$ npm i --save egg-mysql- 开启插件:
// config/plugin.js
exports.mysql = {
enable: true,
package: 'egg-mysql',
};- 配置
// config/config.${env}.js
exports.mysql = {
// 单数据库信息配置
client: {
// host
host: 'mysql.com',
// 端口号
port: '3306',
// 用户名
user: 'test_user',
// 密码
password: 'test_password',
// 数据库名
database: 'test',
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};4. 安装并配置 egg-sequelize
- 安装
$ npm install --save egg-sequelize mysql2- 开启插件
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};- 配置插件
config.sequelize = {
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
database: 'egg-sequelize-doc-default',
// 用户名
user: 'test_user',
// 密码
password: 'test_password',
// 东八时区 (使用sequelize内置时间时用到)
timezone: '+08:00',
};5. eggjs路由群组
目前支持这三种属性
路由别名前缀: name
路由url前缀: prefix
中间件: middlewares
- 安装
$ npm i egg-router-group --save- 开启插件
// {app_root}/config/plugin.js
exports.routerGroup = {
enable: true,
package: 'egg-router-group',
};- 基本用法
// {app_root}/app/router.js
module.exports = app => {
const { router, controller, middleware } = app;
const m1 = middleware.m1();
const m2 = middleware.m2({ key: 'value' });
const m3 = middleware.m3();
router.group({ name: 'home::', prefix: '/pre', middlewares: [ m1, m2 ] }, router => {
// router-path: /pre/test, middlewares: m1, m2
// router-path: /pre/test2, middlewares: m1, m2
router.get('/test', controller.home.test).get('/test2', controller.home.test);
// router-name: home::post, router-path: /pre/post, middlewares: m1, m2, m3
router.post('post', '/post', m3, controller.home.post);
// others
router.all('/test', controller.home.all1);
router.all('testname', '/test2', controller.home.all2);
router.put('/put', controller.home.put);
router.delete('/delete', controller.home.delete);
router.del('/del', controller.home.del);
router.options('/options', controller.home.options);
router.patch('/patch', controller.home.patch);
router.redirect('/redirect', '/');
router.redirect('/redirect2', 'home::testname', 302);
});
// 设置单个属性
router.group({ name: 'home::' }, router => {
// router-path: /test
router.get('/test', controller.home.test);
// router-name: home::post, router-path: /post
router.post('post', '/post', controller.home.post);
});
// group 同样支持链式操作
router.group({ name: 'home::', prefix: '/pre', middlewares: [ m1, m2 ] }, router => {
// router-path: /pre/test, middlewares: m1, m2
// router-path: /pre/test2, middlewares: m1, m2 ⚠️这里🈶️group 设置的属性哦
router.get('/test', controller.home.test).get('/test2', controller.home.test);
})
.get('/test3', controller.home.test); // router-path: /test3 ⚠️这里🈚group 设置的属性哦
};- 中间件
支持传单个中间件或数组的形式
// {app_root}/app/router.js
module.exports = app => {
const { router, controller, middleware } = app;
const m1 = middleware.m1();
const m2 = middleware.m2({ key: 'value' });
router.group({ middlewares: [ m1, m2 ] }, router => {
router.get('/test_m1', controller.home.test_m1);
router.post('/test_m2/:id', controller.home.test_m2);
});
router.group({ middlewares: m1 }, router => {
router.get('/test_m3', controller.home.test_m3);
router.post('/test_m4/:id', controller.home.test_m4);
});
};- 路由别名前缀 & 路由url前缀
路由别名前缀 & 路由url前缀 只支持string类型
// {app_root}/app/router.js
module.exports = app => {
// name
router.group({ name: 'home::' }, router => {
// router-name: home::post
router.post('post', '/test/:id', controller.home.t1);
});
// prefix
router.group({ prefix: '/pre' }, router => {
// router-name: test, router-path: /pre/test2
router.get('test', '/test2', controller.home.t2);
});
};6. sequelize+migration(可以不使用)
- 安装 sequelize-cli
npm install --save-dev sequelize-cli- 新建 .sequelizerc 配置文件
在 egg 项目中,我们希望将所有数据库 Migrations 相关的内容都放在 database 目录下,所以我们在项目根目录下新建一个 .sequelizerc 配置文件:
'use strict';
const path = require('path');
module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'app/model'),
};- 初始化 Migrations 配置文件和目录
npx sequelize init:config
npx sequelize init:migrations- 数据库配置
执行完后会生成 database/config.json 文件和 database/migrations 目录,我们修改一下 database/config.json 中的内容,将其改成我们项目中使用的数据库配置:
{
"development": {
"username": "root",
"password": null,
"database": "egg-sequelize-doc-default",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "egg-sequelize-doc-unittest",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
- 创建表
此时 sequelize-cli 和相关的配置也都初始化好了,我们可以开始编写项目的第一个 Migration 文件来创建我们的一个 users 表了。
npx sequelize migration:generate --name=init-users执行完后会在 database/migrations 目录下生成一个 migration 文件(${timestamp}-init-users.js),我们修改它来处理初始化 users 表:
'use strict';
module.exports = {
// 在执行数据库升级时调用的函数,创建 users 表
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE, STRING } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
},
// 在执行数据库降级时调用的函数,删除 users 表
down: async queryInterface => {
await queryInterface.dropTable('users');
},
};- 执行 migrate 进行数据库变更
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all执行之后,我们的数据库初始化就完成了。
7. 使用sequelize-auto生成sequelize的Models(可以不使用)
- 全局安装sequelize-auto
npm install -g sequelize-auto- 全局安装对应数据库的驱动,此处使用的是mysql
npm install -g mysql- 在对应的文件夹下执行以下命令
sequelize-auto -h 数据库的IP地址 -d 数据库名 -u 用户名 -x 密码 -p 端口 -t 表名- 使用第三步生成的Models
const Sequelize = require('sequelize');
const SequelizeInstance = require('../../config/db'); // sequelize的实例
const User = require('../../models/user')(SequelizeInstance, Sequelize); // 导入用户的模型#$ 8. 编写model文件
根据自己创建的user表映射model文件
参考sequelize Datatypes 数据类型(https://demopark.github.io/sequelize-docs-Zh-CN/data-types.html)
// model/user.js
'use strict';
module.exports = app => {
const { DATE, STRING, INTEGER, UUID, DataTypes } = app.Sequelize;
const User = app.model.define(
'user',
{
id: {
type: INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
uuid: {
type: UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
username: STRING(50),
password: STRING(50),
avator: STRING,
sex: STRING(4),
created_at: DATE(6),
},
{
freezeTableName: true, // Model 对应的表名将与model名相同; (默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数.freezeTableName: true则不转换)
underscored: true, // 自动设置所有属性的字段参数为下划线命名方式. 不会覆盖已经定义的字段选项
// tableName: 'user', // 定义表的名称
// 不要忘记启用时间戳!
// 自动写入时间戳 created_at updated_at
timestamps: true,
// 字段生成软删除时间戳 deleted_at
paranoid: true,
createdAt: 'created_at',
// 我不想要 updatedAt
updatedAt: false,
}
);
return User;
};
9. 使用sequelize操作数据库
调用:ctx.model.User (User开头大写是因为定义的model中return的是User,注意和自己写的对应起来)
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async register() {
const { ctx } = this;
console.log(ctx.request.body);
const { username, password } = ctx.request.body;
const result = await ctx.model.User.create({ username, password });
console.log(result);
if (result) {
this.ctx.body = '注册成功';
} else {
this.ctx.body = '注册失败';
}
}
async login() {
const { ctx } = this;
console.log(ctx.request.body);
const { username, password } = ctx.request.body;
const result = await ctx.model.User.findOne({
where: { username, password },
});
console.log(result);
if (result) {
this.ctx.body = '登录成功';
} else {
this.ctx.body = '登录失败';
}
}
}
module.exports = HomeController;10. jwt鉴权
这里使用插件egg-passport 、egg-passport-jwt、jsonwebtoken。
先安装jsonwebtoken、egg-passport,然后安装egg-passport-jwt。这有个坑,在egg-passport-jwt安装文档上没有说要求安装egg-passport。