逐步搭建
为了让自己更好的了解Egg.js,全部手动一步步搭建(前面都是参考的官网上的内容)。
初始化项目
初始化目录结构:
$ mkdir egg-example
$ cd egg-example
$ npm init
$ npm i egg --save
$ npm i egg-bin --save-dev
添加 npm scripts 到 package.json
{
"name": "egg-example",
"scripts": {
"dev": "egg-bin dev"
}
}
编写Controller
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
this.ctx.body = 'Hello world';
}
}
module.exports = HomeController;
配置路由映射
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
};
加一个配置文件:
exports.keys = <此处改为你自己的 Cookie 安全字符串>;
此时目录结构如下:
egg-example
├── app
│ ├── controller
│ │ └── home.js
│ └── router.js
├── config
│ └── config.default.js
└── package.json
好,现在可以启动应用来体验下
$ npm run dev
$ open http://127.0.0.1:7001
项目初步搭建已完成。
Egg.js是基于MVC模式的,
- app.router.js: 用于配置URL路由规则;
- app/controller/… : 用于解析用户的输入,处理返回相应的结果;
- app/service/… : 用户编写业务逻辑层,关于数据库处理的操作;
- app/model/… : 存放实体类,与数据库中的属性值基本保持一致;
- app/public/… : 用于放置静态资源;
- config/config.config.{env}.js: 用于编写配置文件;
- config/plugin.js 用于配置需要加载的插件;
Sequelize
使用 sequelize 插件自动管理数据层代码。(在此之前本机上已经安装好了MySQL)
安装
安装并配置 egg-sequelize-auto 插件(它会辅助我们将定义好的 Model 对象加载到 app 和 ctx 上)和 mysql2 模块:
npm install -g egg-sequelize-auto mysql2
在 config/pulgin.js 中引入 egg-sequelize插件
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};
在 config/config.default.js 中编写 sequelize 配置
config.sequelize = {
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
database: 'egg-sequelize-doc-default',
};
- dialect : 数据库类型;
- host : 数据库的IP地址;
- port : 端口号;
- database: 数据库名
自动创建Model
这里跳过了数据库初始化的过程,我使用的工具已经创建好了数据库和表,现在通过插件自动创建 Model 。
egg-sequelize-auto -o "./app/model" -d glsx_audit -h 192.168.*.*** -u root -p 3308 -x 123456 -e mysql
参数说明
- -h 数据库的IP地址;
- -d 数据库名;
- -u 用户名;
- -x 密码;
- -p 端口;
- -e 数据库类型;
- -t 表名, 不指定-t , 为所有表;
在创建时碰到的问题,数据库error:1045
sqlMessage: 'Access denied for user \'root\'@'192.168.*.***\' (using passwork: YES)'
原因:密码为字符串; 解决办法:字符串要使用双引号,不可以使单引号;
egg接收请求参数
get请求
async getList() {
const query = this.ctx.query
...代码
}
或者
async getList(query) {
...代码
}
post请求
async create() {
const data = this.ctx.request.body
...代码
}
或者
async create({request: { body } }) {
const data = this.ctx.request.body
...代码
}
接口返回值
this.ctx.body = {
code: 0,
data: '返回的数据',
msg: '返回状态信息'
}
增删改查
查询
service.js
分页查询
async findAll({pager = {},searcher = {}}) {
const { current = 1, size = 10 } = pager
const {projectName } = searcher
const offset = (current - 1) * size
const { Op } = this.app.Sequelize
if (projectName) {
const __like = `%${projectName}%`
where.project_name(数据库中的字段) = {
[Op.like]: __like
}
}
return await projectModel(表别名).findAndCountAll({
offset,
limint: +size,
where,
raw: true
})
}
计算和的所有数据
return await AModel.findAll({
attributes: [
[fn.('SUM', col('delivery_total')), 'deliveryTotal']
],
where,
raw: true
})
接口返回指定数据
const attr = ['merchant_id', 'merchant_name', 'account_name', 'merchant_type', 'address', 'phone', [fn.('SUM', col('delivery_total')), 'deliveryTotal']]
return await AModel.findAll({
attributes: attr,
where,
raw: true
})
删除选定的属性
attributes: {exclude: ['id', 'delete_flag']
新增
service.js
async create(params) {
const now = Date.now()
const p = await this.DI.create({
...
created_at: now,
updated_at: now,
del_flag: 'Y'
})
return {
id: p.id
}
}
注意:新增的时候会默认生成两个字段 created_at、updated_at ,数据库插入数据会导致报错找不到该字段,我的处理方式是在数据库里直接创建相同的字段。
修改
service.js
async update(params) {
const id = params.id
const u = await projectModel.findById(id)
u.update(params)
return u
}
或者
async update(params) {
return await projectModel.update(params)
}
删除
service.js
async delete({id}) {
const d = await projectModel.destroy({
where: {
id: id
}
})
return d
}
调用后台接口
有时候需要从别的服务上调用接口,获取数据。方式如下:
async search() {
const ctx = this.ctx
let params = ''
const result = await ctx.curl(`http://....?${params}`, {
dataType: 'text',
method: 'GET',
timeout: 3000
})
return result
}
安全威胁 钓鱼攻击 的防范
报错提示:
invalid csrf token. See https://eggjs.org/zh-cn/core/security.html
防范方式
在 config.default.js 中配置
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ["http://localhost:8080"]
};
若用户没有配置 domainWhiteList 或者 domainWhiteList数组内为空,则默认会对所有跳转请求放行
暂时记录到这里,后面又遇到问题在更新。
|