一、创建项目
1、全局安装
npm i egg-init -g
2、初始化项目
新建项目文件夹后,npm init egg --type=simple
3、安装依赖
npm install
4、启动
测试:npm run dev
正式:npm run start
\
二、架构介绍(app)
eggjs是一个mvc的框架,约定优于配置
1、service
模型,和数据打交道,查询数据库、请求数据。(eggjs中service属于mvc架构中的model)
(1)controller获取service数据
const list = await this.service.news.getNewsList();
(2)service之间可以互相调用
(3)this.ctx.curl(url,{}) 发起网络调用
2、view
模版渲染,用于视图、模版、页面的展示。
(1)ejs的使用
3、controller
this.ctx.body 用于返回数据
this.ctx.query 获取query的值
this.ctx.params 获取动态路由传值
this.ctx.request.body 用于获取post等方式的body请求数据
await this.ctx.render('news',{a:1,b:2}) 调用render渲染文件,并传递数据
4、router.js
用于路由配置
5、middleware(中间件)
中间件,加载路由前进行权限判断
(1)全局中间件的使用
//config.default.js 访问全部路由都会生效
config.middleware = ["auth"];
传参
//config.default.js
config.auth={
title:"this is title"
}
//middleware auth.js
module.exports = (option,app)=>{
return async function auth(ctx,next){
console.log(option);
console.log(new Date());
await next();
}
}
(2)路由中中间件的使用
//router.js
var auth = app.middleware.auth({title:"router title"});
router.get('/', auth, controller.home.index);
(3)框架中间间的默认配置
config.bodyParser = {
jsonLimit: '10mb' //default is 1mb
}
(4)使用koa中间件
规范的koa中间件
//1、安装
npm install koa-jsonp
//2、middleware/jsonp.js
var jsonp = require('koa-jsonp');
module.exports = jsonp;
//3、config.default.js
config.middleware = ['jsonp'];
koa-compress //用于压缩页面大小,加快响应速度
//3、config.default.js
config.compress = {
threshold:100 //它支持指定只有当body大于配置的threshold时,才进行gzip压缩,默认1024
}
非标准的koa中间件 (包含多个option)
//middleware/Middleware.js
const Middleware = require('some-koa-middleware');
module.exports = (option,app)=>{
return Middleware(option.xxx,option.xxx);
}
(5)中间件通用属性
enable:控制中间件是否开启。
match:设置只有符合某些规则的请求才会经过这个中间件。
ignore:设置符合某些规则的请求不经过这个中间件。
match和ignore不能同时使用
//普通使用
config.auth = {
enable:false,
match:'/news',
title:'随便一个传参'
}
//高级使用
config.auth = {
enable:true,
match(ctx){
if(ctx.request.url == "/shop" || ctx.request.url == "/news") return true;
return false;
},
title:'随便一个传参'
}
\
6、extend
对application、context、request、response、helper对象进行自定义拓展,进一步加强框架的功能
\
7、public
存放静态资源 访问方法 /public/xxx/xxx.xxx
\
8、定时任务(schedule)
(1)所有定时任务存放在app/schedule目录下
(2)使用方法
//标准写法
const Subscription = require('egg').Subscription;
var i = 0;
class Test extends Subscription{
static get schedule() {
return {
interval: '3s', // 时间间隔
type: 'all', // 指定所有的 worker(进程) 都需要执行
disable:false //是否关闭定时任务,false不关闭
};
}
// subscribe 是真正定时任务执行时被运行的函数
async subscribe() {
//定时任务执行的操作
++i;
console.log(i);
}
}
module.exports = Test;
//简单写法
module.exports = {
schedule: {
interval: '3s', // 3秒间隔
type: 'all', // 指定所有的 worker 都需要执行
disable:false //是否关闭定时任务,false不关闭
},
async task(ctx) {
const result = await ctx.service.home.getNews();
console.log(result);
},
};
//动态配置定时任务
//config.default.js
config.scheduleTime = '3s'
//schedule/test.js
module.exports = app => {
return{
schedule: {
interval: app.config.scheduleTime, // 1 分钟间隔
type: 'all', // 指定所有的 worker 都需要执行
disable:false //是否关闭定时任务,false不关闭
},
async task(ctx) {
const result = await ctx.service.home.getNews();
console.log(result);
},
}
};
(3)cron
通过 schedule.cron 参数来配置定时任务的执行时机,定时任务将会按照 cron 表达式在特定的时间点执行。cron 表达式通过 cron-parser 进行解析。
注意:cron-parser 支持可选的秒(linux crontab 不支持)
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ |
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, optional)
示例:
module.exports = {
schedule: {
// 每三小时准点执行一次
cron: '0 0 */3 * * *',
},
};
三、config(配置)
1、config.default.js
//配置项
config.api = "http://www.cqcode.cn"
//其他文件访问配置项
this.config.api
2、plugin.js
(1)引入插件方法
//例如引入ejs
module.exports = {
ejs:{
enable: true,
package:'egg-view-ejs'
}
};
四、mysql
mysql文档:www.yuque.com/cqcode/node…
1、安装和引入
(1)安装
npm i --save egg-mysql
(2)引入
// config/plugin.js
exports.mysql = {
enable: true,
package: 'egg-mysql',
};
2、连接数据库(单数据源)
// config/config.default.js
config.mysql = {
// 单数据库信息配置
client: {
// host
host: 'mysql.com',
// 端口号
port: '3306',
// 用户名
user: 'test_user',
// 密码
password: 'test_password',
// 数据库名
database: 'test',
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};
3、查询
使用get查询一条,select查询符合条件的全部
const res = await app.mysql.select('order',{
where:{state:ctx.query.state}, // WHERE 条件
columns: ['author', 'title'], // 要查询的表字段
orders: [['created_at','desc'], ['id','desc']], // 排序方式
limit: 10, // 返回数据量
offset: 0, // 数据偏移量
});
4、插入
// 在 post 表中,插入 title 为 Hello World 的记录‘
const result = await this.app.mysql.insert('posts', { title: 'Hello World' });
// 判断插入成功
const insertSuccess = result.affectedRows === 1;
5、更新
// 1、修改数据,将会根据主键 ID 查找,并更新
const row = {
id: 123,
name: 'fengmk2',
otherField: 'other field value', // any other fields u want to update
modifiedAt: this.app.mysql.literals.now, // `now()` on db server
};
const result = await this.app.mysql.update('posts', row); // 更新 posts 表中的记录
// 判断更新成功
const updateSuccess = result.affectedRows === 1;
// 2、如果主键是自定义的 ID 名称,如 custom_id,则需要在 `where` 里面配置
const row = {
name: 'fengmk2',
otherField: 'other field value', // any other fields u want to update
modifiedAt: this.app.mysql.literals.now, // `now()` on db server
};
const options = {
where: {
custom_id: 456
}
};
const result = await this.app.mysql.update('posts', row, options); // 更新 posts 表中的记录
6、删除
const result = await this.app.mysql.delete('posts', {
author: 'fengmk2',
});
7、sequelize
安装
npm i --save egg-sequelize
npm install --save mysql2
引入
//plugin.js
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};
exports.mysql = {
enable: true,
package: 'egg-mysql',
};
//config.default.js
config.sequelize = {
delegate: 'model', // load all models to app.model and ctx.model
baseDir: 'model', // load models from `app/model/*.js`
dialect: 'mysql', // support: mysql, mariadb, postgres, mssql
database: '',
host: '',
port: 3306,
username: '',
password: '',
define: {
freezeTableName: true,
},
};
使用
//创建
const res = await ctx.model.AdBgmCls.create({
cls: cls_name,
});
//批量创建
const res = await ctx.model.AdBgmCls.bulkCreate({
cls: cls_name,
});
//查询
const res = await ctx.model.AdBgmCls.findOne({
where: {
id:task.id,
},
});
//批量查询
const res = await ctx.model.AdBgm.findAll({
where: {
status: 0,
},
order: [
['create_time', 'DESC'],
['usage_count', 'DESC']
],
});
//查询并计数
findAndCountAll
//更新1 update
const res = await ctx.model.AdBgm.update({
status: 1,
}, {
where: {
id,
}
});
//更新2 save
const effect = await ctx.model.Effect.findOne({id});
if(effect && effect.status === 0) {
effect.status = 1;
await effect.save();
}
//插入或更新
const res = await ctx.model.AdBgmCls.upsert({
cls: cls_name,
});
//删除
const result = await this.ctx.model.AdTplResult.destroy({
where: {
tpl_id,
},
});
复杂使用
1、查询json长度不等于0 且 名字不等于陈琦的数据
SELECT * FROM `home` AS `home`
WHERE NOT ((json_length(`data`) = 0 OR `home`.`name` = 'chenqi'));
⬇️
const res = await this.ctx.model.Home.findAll({
attributes: ['name'],
where:{
[Op.not]:[
{
[Op.or]:[
Sequelize.where(Sequelize.fn('json_length', Sequelize.col('data')), 0),
{
name:name
}
]
}
]
}
});
model
'use strict';
module.exports = (app, model) => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const AdBgm = model.define('ad_bgm', {
id: {
type: INTEGER,
primaryKey: true,
autoIncrement: true,
},
user_id: STRING,
name: STRING,
addr: STRING,
size: STRING,
cls: STRING,
music_start_time: STRING,
duration: STRING,
usage_count: INTEGER,
status: INTEGER, // 0 正常 1 删除
create_time: DATE,
update_time: DATE,
}, {
timestamps: false,
});
return AdBgm;
};
\
\
五、安全风险
1、csrf
在config.default.js关闭或开启csrf
exports.security = {
csrf: {
enable: false,
},
};
六、第三方包
1、moment.js
安装
npm i --save moment
引入
//在controller中引入
const moment = require('moment');
使用
const params = {
...ctx.request.body,
createTime:moment().format('YYYY-MM-DD HH-dd-ss')
}
扩展
//增加日期
moment().add(1,'year').format('YYYY-MM-DD hh:mm:ss')
//减少日期
moment().subtract(1,'days').format('YYYY-MM-DD hh:mm:ss')
\
2、egg-jwt
安装
npm install egg-jwt --save
引入
//config/plugin.js
exports.jwt = {
enable: true,
package: "egg-jwt"
};
//config/config.default.js
config.jwt = {
secret: "cqyyds"//自定义 token 的加密条件字符串
};
使用
//router.js 限制接口需要jwt验证,用户已经获取token后使用,限制无token用户
router.post('/order/changeState',jwt,controller.order.changeState);
//controller 登陆成功返回token
const token = app.jwt.sign({
username: ctx.request.body.username //存放用于存储的用户数据,ctx.state.username可全局获取
}, app.config.jwt.secret);
ctx.body = token;
前端使用
headers:{
// 切记 token 不要直接发送,要在前面加上 Bearer 字符串和一个空格
'Authorization':`Bearer ${token}`
}
\
3、egg-cors(跨域问题解决)
安装
npm install egg-cors
配置
//config/plugin.js
exports.cors = {
enable: true,
package: 'egg-cors',
}
//config.default.js
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['*'],//允许访问接口的白名单
};
config.cors = {
origin:'*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
};
七、部署到服务器
1、配置端口号
//config.default.js
config.cluster = {
listen: {
port: 7001,
hostname: '127.0.0.1',
// path: '/var/run/egg.sock'
}
}
2、发布
(1)去除node_modules移动项目到服务器
(2)cd到项目文件 如:cd /usr/local/nginx/server/catz-server
(3)npm install --production
(4)npm start
此时服务已经在配置好的端口号开启,但把此端口暴露出去是不安全的,需要通过nginx转发
3、配置nginx转发到端口
//cd /usr/local/nginx/conf/
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /api/blog/ {
proxy_pass http://127.0.0.1:6001/;
}
location /api/catz/ {
proxy_pass http://127.0.0.1:6002/;
}
}
如未生效,重启nginx
nginx -s reload
4、参考链接
nginx:www.cnblogs.com/paul123/p/1…
eggjs发布:blog.csdn.net/qq_37162688…
八、标准化项目搭建
九、serverless构建eggjs
控制台:console.cloud.tencent.com/sls
1、安装serverless
npm install -g serverless
serverless -v
2、创建项目
serverless
3、部署
serverless deploy
4、serverless.yml 配置不上传文件
component: http
name: eggshop
inputs:
src:
src: ./
exclude:
- .env
- .git
- node_modules
faas:
runtime: Nodejs12.16
framework: egg
name: '${name}'
apigw:
protocols:
- http
- https
app: eggshop