一、创建安装egg脚手架

1.安装脚手架

npm init egg --type=simple

2.安装依赖

npm i

3.运行

npm run dev

二、配置数据库

1.安装数据库插件

npm install --save egg-sequelize mysql2

2.开启插件

config/plugin.js 中引入 egg-sequelize 插件

sequelize: {enable: true,package: 'egg-sequelize',
}

3.配置数据库

文件路径:config/config.default.js

config.sequelize = {dialect:  'mysql',host:  '127.0.0.1',username: 'root',password:  'root',port:  3306,database:  '数据库表名',// 中国时区timezone:  '+08:00',define: {// 取消数据表名复数freezeTableName: true,// 自动写入时间戳 created_at updated_attimestamps: true,// 字段生成软删除时间戳 deleted_at// paranoid: true,createdAt: 'created_at',updatedAt: 'updated_at',// deletedAt: 'deleted_at',// 所有驼峰命名格式化underscored: true}
};

4.创建数据库(也可以自己手动创建)

用命令创建

1.安装插件

npm install --save-dev sequelize-cli

2.创建配置文件

路径:根目录下穿件.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'),
};

3.初始化 Migrations 配置文件和目录

以下两个命令在整个项目中只需要运行一次

npx sequelize init:config
npx sequelize init:migrations

运行完以上命令后根目录下会多出一个database文件夹

database文件夹下会有migarations目录和config.json文件

config.json文件中有三个对象

development:代表开发环境

test:代表测试环境

production:代表生产环境

4.配置以上三个环境中的数据库参数

{"development": {"username": "root","password": root,"database": "数据库名","host": "127.0.0.1","dialect": "mysql","timezone": "+08:00"}
//以下两个同上
}

5.创建数据库

npx sequelize db:create

这时候数据库中会多了一个数据库

库名为三个环境中database中配置的名称

6.创建数据表

创建数据表

npx sequelize migration:generate --name=init-user

执行完以上命令后migarations目录下会多出一个xxxxxx-init-user.js文件

7.配置数据表

database/migarations/xxxxxx-init-user.js文件

'use strict';module.exports = {async up (queryInterface, Sequelize) {const {INTEGER,STRING,DATE,ENUM} = Sequelize;await queryInterface.createTable('user',{id:{type:INTEGER(20).UNSIGNED,  //UNSIGNED代表无符号primaryKey:true,  //主键autoIncrement:true //自动递增},username:{type:STRING(30),allowNull:false, //是否允许为空defaultValue:'', //默认值为空comment:'用户名称', //备注unique:true  //是否是唯一的},password:{type:STRING(200),allowNull:false,defaultValue:''},avatar_url:{type:STRING(200),allowNull:false,defaultValue:''},sex:{type:ENUM,values:['男','女','保密'],allowNull:true,defaultValue:'男',comment:'用户性别'},created_at:DATE,updated_at:DATE})},async down (queryInterface, Sequelize) {await queryInterface.dropTable('user')}
};
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all

此时数据表已经创建完成。

8.创建数据模型

用途:某个表的增删改查

创建:app/model/表名.js

'use strict';
module.exports = app => {const { STRING,INTEGER, DATE, ENUM } = app.Sequelize;const User = app.model.define('user',{id:{type:INTEGER(20).UNSIGNED,  //UNSIGNED代表无符号primaryKey:true,  //主键autoIncrement:true //自动递增},username:{type:STRING(30),allowNull:false, //是否允许为空defaultValue:'', //默认值为空comment:'用户名称', //备注unique:true  //是否是唯一的},password:{type:STRING(200),allowNull:false,defaultValue:'',/*** 修改器set(val){//可以在这对密码进行加密,然后let hash = 加密命令this.setDataValue('password',hash)}* */},avatar_url:{type:STRING(200),allowNull:false,defaultValue:''},sex:{type:ENUM,values:['男','女','保密'],allowNull:true,defaultValue:'男',comment:'用户性别'},created_at:{type:DATE,//转换成时间戳get(){const val = this.getDataValue('created_at');return (new Date(val)).getTime();}},updated_at:{type:DATE,//转换成时间戳get(){const val = this.getDataValue('updated_at');return (new Date(val)).getTime();}}});return User;
}

其他参数,随用随添加

//自定义表名
'freezeTableName':true,
'tableName':'xxxxxx',//是否需要增加createdAt、updatedAt、deletedAt字段
'timestamps':true,//不需要createdAt字段
'createdAt':false,//将updatedAt字段改革名
'updatedAt':'新名',//将deletedAt字段改名
//同时需要设置paranoid为true(此种模式下,删除数据时不会进行物理删除,二十设置deletedAt为当前时间)
'deletedAt':'dtimm',
'paranoid':true,//此参数需要配置在app/model/控制器/updated:DATE
//    },{
//这里面
//}

9.增删改查

await this.app.model.User.方法名

//单个
create(obj)
//批量
bulkCreate(Array)

//删除单个
async delet(){let id = this.ctx.params.id ? parseInt(this.ctx.params.id) : 0;let data = await this.app.model.User.findByPk(id);if(!data){return this.ctx.body = {msg:'fail',data:"该数据不存在。"};}let res = await data.destroy();this.ctx.body = {msg:'ok',data:res  }};//删除多个
async deletMore(){const Op = this.app.model.Sequelize.Op;let data = await this.app.model.User.destroy({where:{id:{[Op.lte]:7 //删除id小于7的数据}}});this.ctx.body = {msg:'ok',data:res  }};

//连接中需要传要修改的id过来//首先获取idlet id = this.ctx.params.id ? parseInt(this.ctx.params.id) : 0;//获取指定的记录let data = await this.app.model.User.findByPk(id);let params = this.ctx.request.body;//判断数据是否存在if(!data){return this.ctx.body = {msg:"fail",data:"该记录不存在。"}}//let res = await data.update(params,{fielda:['username']}); //添加{fielda:['username']}标识仅仅修改username字段,其余的均不更改let res = await data.update(params);this.ctx.body = {msg:"ok",data:res}}

//单个,无条件
findByPk(parseInt(id));  //parseInt转换成int类型
//单个,加条件过滤
findOne({where:{id:2,sex:"女",条件....}
})const Op = this.app.Sequelize.Op;
findAndCountAll({where:{username:{[Op.like] : "%5%"},条件:{.....}}
});//全部
findAll()
可以加条件方法:
过滤参数
只显示数组中的参数:
attributes:['username','sex',...]
相反:
attributes:{exclude:['password']  //除了password不显示,其余均显示
}//排序,如果没作用,调换一下条件顺序试试
order:[['id','DESC'],  //DESC降序,ASC升序条件...
]//分页
首先在连接中需要加入页码参数?page=1
在查询的开始就要拿到page的参数
let page = this.ctx.quer.page ? parseInt(this.ctx.quer.page) : 1;  //页码
let limit = 5;
let offset = (page - 1) * 5; //计算偏移//以下写到findAll()方法中的一级和where是同级
offset, //偏移,从哪开始
limit  //显示5条//查全部并计数
findAndCountAll()

Op参数

[Op.and]: {a: 5}           // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}]  // (a = 5 或 a = 6)
[Op.gt]: 6,                // id > 6
[Op.gte]: 6,               // id >= 6
[Op.lt]: 10,               // id < 10
[Op.lte]: 10,              // id <= 10
[Op.ne]: 20,               // id != 20
[Op.eq]: 3,                // = 3
[Op.not]: true,            // 不是 TRUE
[Op.between]: [6, 10],     // 在 6 和 10 之间
[Op.notBetween]: [11, 15], // 不在 11 和 15 之间
[Op.in]: [1, 2],           // 在 [1, 2] 之中
[Op.notIn]: [1, 2],        // 不在 [1, 2] 之中
[Op.like]: '%hat',         // 包含 '%hat'
[Op.notLike]: '%hat'       // 不包含 '%hat'
[Op.iLike]: '%hat'         // 包含 '%hat' (不区分大小写)  (仅限 PG)
[Op.notILike]: '%hat'      // 不包含 '%hat'  (仅限 PG)
[Op.regexp]: '^[h|a|t]'    // 匹配正则表达式/~ '^[h|a|t]' (仅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正则表达式/!~ '^[h|a|t]' (仅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]'    // ~* '^[h|a|t]' (仅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (仅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何数组['cat', 'hat'] - 同样适用于 iLike 和 notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG数组重叠运算符)
[Op.contains]: [1, 2]      // @> [1, 2] (PG数组包含运算符)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG数组包含于运算符)
[Op.any]: [2,3]            // 任何数组[2, 3]::INTEGER (仅限PG)
[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用数据库语言特定的列标识符, 本例使用 PG

三、关闭csrf开启跨域

1.安装save

npm i egg-cors --save

2.配置插件

文件路径:config/plugin.js

//跨域
cors:{enable: true,package: 'egg-cors',
},

3.关闭csrf开启跨域

文件路径:config/config.default.js

全局关闭

config.security = {// 关闭 csrfcsrf: {enable: false,},// 跨域白名单domainWhiteList: [],};// 允许跨域的方法config.cors = {origin: '*',allowMethods: 'GET, PUT, POST, DELETE, PATCH'};//写在这的上边
//return{
//...config,
//...xxxxx
//}

过滤关闭(这里表示凡是以/api开头的路由都不需要经过csrf验证)

 config.security = {//关闭 csrf//api这个就不需要用csrf验证,所以用这段代码可以排除掉以/api开头的请求csrf: {headerName:'x-csrf-token',ignore:ctx => {return ctx.request.url.startsWith('/api')}},// 跨域白名单domainWhiteList: [],};// 允许跨域的方法config.cors = {origin: '*',allowMethods: 'GET, PUT, POST, DELETE, PATCH'};

四、中间件

错误异常处理

1.新建文件夹 app/middleware

2.新建中间件文件 app/middleware/error_hendler.js

module.exports = () => {return async function errorHandler(ctx,next){try {await next();}catch(err){ctx.app.emit('error',err,ctx);const status = err.status || 500;const error = status === 500 && ctx.app.config.env === 'prod'? 'Internal Server Error' : err.message;ctx.body = { error};if(status === 422){ctx.body.detail = err.errors;}ctx.status = status}};
};

4.开启中间件

app/config/config.default.js

// add your middleware config here

config.middleware = ['errorHendler'];

5.配置中间件

app/config/config.default.js

在config.middleware = ['errorHendler'];下继续写配置

config.errorHendler= {enable:true,  //是否开启中间件match:["/user/list"]  //设置哪些路由走中间件//ignore:["/user/list"]  //设置哪些路由不走中间件/**1.match和ignore不能同时使用2.例如:match:["/user"],只要包含/user的任何页面都生效**///match和ignore支持多种类型配置方式:字符串、正则、函数(推荐)match(ctx){//只有ios设备才开启const res = /iphone|ipad|ipod/i;return res.test(ctx.get('user-agent'));}
};

五、参数验证

安装插件

npm i egg-valparams --save

配置插件

//config/plugin.jsvalparams : {enable : true,package: 'egg-valparams'},//app/config/config.default.jsconfig.valparams = {locale : 'zh-cn',throwError: true
};//使用
/*获取传过来的参数*/
let params = this.ctx.request.body;
this.ctx.validate({username:{type: 'string', //数据类型required: true, //是否必填desc: '用户名'   //字段描述},password:{type: 'string', required: true, desc: '密码' },sex:{type:'string', required: false, defValue: '保密', //默认值desc: '性别'   }});
//写入数据库

ValParams API 说明

参数验证处理

Valparams.setParams(req, params, options);

Param Type Description Example
req Object request 对象,这里我们就是取相应的三种请求的参数进行参数验证 {params, query, body}
params Object 参数的格式配置 { pname: {alias, type, required, range: {in, min, max, reg, schema }, defValue, trim, allowEmptyStr, desc[, detail] } } {sysID : {alias:'sid',type: 'int', required: true, desc: '所属系统id'}}
params[pname] String 参数名
params[pname].alias String 参数别名,可以使用该参数指定前端使用的参数名称
params[pname].type String 参数类型 常用可选类型有 int, string, json 等,其他具体可见下文或用 Valparams.vType 进行查询
params[pname].required Boolean 是否必须
params[pname].range Object 参数范围控制 {min: '112.80.248.10', max: '112.80.248.72'}
params[pname].range.min ALL 最小值、最短、最早(不同 type 参数 含义有所差异)
params[pname].range.max ALL 最大值、最长、最晚(不同 type 参数 含义有所差异)
params[pname].range.in Array 在XX中,指定参数必须为其中的值
params[pname].range.reg RegExp 正则判断,参数需要符合正则
params[pname].range.schema Object jsonSchema,针对JSON类型参数有效,使用ajv对参数进行格式控制
params[pname].defValue ALL 默认值,没传参数或参数验证出错时生效,此时会将该值赋值到相应参数上
params[pname].trim Boolean 是否去掉参数前后空格字符,默认false
params[pname].allowEmptyStr Boolean 是否允许接受空字符串,默认false
params[pname].desc String 参数含义描述
options Object 参数关系配置
options.choices Array 参数挑选规则 [{fields: ['p22', 'p23', 'p24'], count: 2, force: true}] 表示'p22', 'p23', 'p24' 参数三选二
options.choices[].fields Array 涉及的参数
options.choices[].count Number 需要至少传 ${count} 个
options.choices[].force Boolean 默认 false,为 true 时,涉及的参数中只能传 ${count} 个, 为 false 时,可以多于 ${count} 个
options.equals Array 参数相等 [['p20', 'p21'], ['p22', 'p23']] 表示 'p20', 'p21' 两个值需要相等,'p22', 'p23' 两个值需要相等
options.equals[] Array 涉及的参数(涉及的参数的值需要是相等的)
options.compares Array 参数大小关系 [['p25', 'p26', 'p27']] 表示 'p25', 'p26', 'p27' 必须符合 'p25' <= 'p26' <= 'p27'
options.compares[] Array 涉及的参数(涉及的参数的值需要是按顺序从小到大的)
options.cases Object 参数条件判断 [{when: ['p30'], then: ['p31'], not: ['p32']}] 表示 当传了 p30 就必须传 p31 ,同时不能传p32
options.cases.when Array 条件
options.cases.when[] String 涉及的参数,(字符串)只要接收到的参数有这个字段即为真
options.cases.when[].field 涉及的参数的名(对象) ---
options.cases.when[].value 涉及的参数的值(对象)需要参数的值与该值相等才为真 ---
options.cases.then Array 符合when条件时,需要必传的参数
options.cases.not Array 符合when条件时,不能接收的参数

功能参数

1.获取get连接的数据

this.ctx.params.xx;   解释:xx代表的是参数

获取url的问号get传值参数

http://127.0.0.1/1?user=2&paw=3

获取1    this.ctx.query.路由名问号后面的参数名

获取2   this.ctx.query.user;

获取3   this.ctx.query.paw;

2.获取psot数据

this.ctx.request.body

3.从某个数组中拿到指定参数的数据

数组名.find(item => item.字段 == 参数);   解释:字段代表对象中的字段名    参数代表指定的参数

4.修改状态码

this.ctx.status = 201;

错误处理

1.ctx is not defined   某的地方缺少this,在ctx前加上this.

2.missing csrf token  关闭跨域

egg+vue后台完整版相关推荐

  1. 微信小程序电影订票系统+SpringBoot后台完整版

    在网上有很多关于电影订票的小程序,但是很多都只是有前端页面,没有后台项目源码,还有的就是用别人家的数据,比如:仿猫眼的,然后说他们限制API接口的使用 最后,本人亲自独立写了一套完成的电影小程序源码, ...

  2. 前端学习 Vue笔记 完整版

    1.1 搭建Vue开发环境 项目导入开发版本文件 <script type="text/javascript" src="../js/vue.js"> ...

  3. 微信小程序 小程序源码包括后台完整版分享

    需要的留邮箱 免费发! 版权归作者所有,任何形式转载请联系作者. 作者:执波仔丶(csdn博客) 最新收集的60个微信小程序源码分享+开发视频教程最新收集的60个微信小程序源码分享+开发视频教程最新收 ...

  4. 手机移动端加载更多(表格首行首列固定vue + vant完整版)

    直接看效果图和实现的代码 <van-list:offset="60"v-model="isLoading":finished="finished ...

  5. vue中组件之间传值的六种方式(完整版)

    前言   组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.一般来说,组件可以有以下几种关系: 如上图所示,A 和 B.B 和 C.B ...

  6. vue组件间通信六种方式(完整版)

    前言   组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.一般来说,组件可以有以下几种关系:                如上图所示 ...

  7. ktv管理系统_7天撸完KTV点歌系统,含后台管理系统(完整版)

    最近手有点痒琢磨着做个啥,朝思暮想还是写个KTV点歌系统,模拟了一下KTV开户的思路,7天累死我了,不过技术点还挺多的,希望你可以看完(〜^㉨^)〜 用Node(Express)教你写KTV点歌系统, ...

  8. 星力+手游运营版本完整版打包下载 代理+服务端+后台+更新+APP

    介绍: 星力+手游运营版本完整版打包下载 代理+服务端+后台+更新+APP 网盘下载地址: https://zijiewangpan.com/AM4tpRbz0L2 图片:

  9. 活动报名发布小程序源码 聚会活动报名小程序完整版前端+后台管理Think

    活动报名发布小程序源码 聚会活动报名小程序完整版前端+后台管理Think下载链接:https://pan.baidu.com/s/16e3egizS_bjuJTv2YcA6Xg 提取码:6n11

最新文章

  1. 嵌套SQL语句訪问DB2中SQLCA的调用技巧
  2. python for in循环_Python傻瓜教程:跟我学for循环
  3. 【Python基础】Python画王者荣耀英雄能力雷达图
  4. 代码覆盖率测试工具:gcov和lcov的使用
  5. hdu 3887 Counting Offspring
  6. 136. 只出现一次的数字 golang
  7. Django之ORM对数据库操作
  8. dbcp连接池配置详解_JDBC第四篇【数据库连接池、DbUtils框架、分页】(修订版)
  9. 更适合Pythoner的标记语言Yaml学习总结
  10. linux json 写sql注入,sql注入之AJAX(SQL Injection (AJAX/JSON/jQuery))
  11. linux释放内存后设备起不来,Linux-Memory小记
  12. tablesorter,jquery
  13. 程序员玩游戏之四--娱网棋牌大连打滚子记牌器
  14. PHP 获取网页标题(title)、描述(description)、关键字(keywords)等meta信息
  15. 手机中.android_secure文件夹中的文件能删除吗,安卓手机里的各“文件夹”都是什么?能删吗?-手机相册在哪个文件夹...
  16. C# 键盘中的按键对应的KeyValue
  17. OCR应用:名片识别
  18. asp.net旅游网站系统VS开发sqlserver数据库web结构c#编程计算机网页项目
  19. js chrome 富文本 恢复光标的办法
  20. vue3+ant design vue+ts实战【ant-design-vue组件库引入】

热门文章

  1. 文档数据恢复工具如何使用
  2. linux常用的软件安装
  3. PCA降维工作原理及代码案例实现
  4. 线性回归(Linear Regression)
  5. 3D打印机耗材ABS和PLA的区别
  6. 台式计算机折旧年限,最新税法规定固定资产电脑折旧年限是多少年
  7. [GKCTF2020]EZ三剑客 记录
  8. 7-6 拿糖果 (15 分)
  9. 软件测试灵魂三问,如何怼回去?
  10. 正则表达式:安琪拉之歌Aquarian文字查找与翻译