egg.js笔记

egg.js

/app 文件夹

/controller

  1. 响应数据或渲染模板
  2. 与用户数据交互
  3. 与路由建立对应关系

控制器里的this

控制器里的 this.app === this.ctx.app

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{ 
ctx: {
request,
response,
app,
originalUrl,
req,
res,
socket
},
app,
config,
service
}

home.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict';
//1. 导入 Controller 是egg提供的控制器类
const { Controller } = require('egg');
//2. 继承 自己定义一个控制器
class HomeController extends Controller {
async index() {
const { ctx } = this;
// ctx.body = 'hi, egg';
ctx.body = '<h1>hello world!!!</h1>';
}
}
//3. 暴露
module.exports = HomeController;

  1. 里面的async index方法即为 index页面

  2. 请求参数解析=== koa2

    但是解析post请求参数不需要koa-body

post请求的安全验证

为了防止 CSRF跨站请求伪造

1
2
3
4
5
config.security = {
csrf: {
enable: false, //关闭此安全检查
}
}
  • 如果不关闭则403: invalid csrf token

重定向

1
this.ctx.redirect('url')

/service

对复杂业务场景进行封装:

 1. 保持controller逻辑简介
 2. service中的业务逻辑可以被复用
1
2
3
4
5
6
7
8
9
// /app/service/myService.js
const Service = require('egg').Service;
class MyService extends Service {
async fun() {
...
}
}

module.exports = MyService;
1
2
//调用
this.ctx.service.myService.fun()

/public

静态文件目录

  • 目录下存在 index.html,可以通过localhost:7001/public/index.html 访问

router.js

1
2
3
4
5
6
7
8
9
10
11
12
// app 是整个egg的实例对象, 从中结构出router和controller
module.exports = (app) => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/news', controller.news.list);
router.get('/fruits', controller.fruits.index);
router.get('/fruits/:id', controller.fruits.getId)

//restful api
router.resources('fruits','/fruits',controller.fruits) //具体到fruits控制器就可以了

};

restful Api

Method Path Route Name Controller.Action
Get /posts posts app.controllers.posts.index
Get /posts/new new_post app.controllers.posts.new
Get /post/:id post app.controllers.posts.show
Get /post/:id/edit edit_post app.controllers.post.edit
Post /posts posts app.controllers.posts.create
Put /posts/:id posts app.controllers.posts.update
Delete /posts/:id posts app.controllers.posts.destroy

需要在controllers/posts.js 下存在 index/new/show/edit/create/update/destroy等方法

/config

config.default.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module.exports = appInfo => {
/**
* built-in config
* @type {Egg.EggAppConfig}
**/
const config = exports = {};

// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_252238Lzy...';

// add your middleware config here (所有路由都生效!!!, 想要单独在某路由上生效,请在控制器里写)
config.middleware = [];

// add your user config here
const userConfig = {
// myAppName: 'egg',
};

config.security = {
csrf: {
enable: false,
}
}

config.view = {
defaultViewEngine: 'nunjucks',
mapping: {
'.tpl': 'nunjucks',
'.html': 'nunjucks'
}
}

//数据库
config.mysql = {
// 单数据库信息配置
client: {
host: 'localhost',
port: '3306',
user: 'root',
password: '252238Lzy',
database: 'mytest',
},

//多源
// clients: {
// db1: {
// host: 'localhost',
// port: '3306',
// user: 'root',
// password: '252238Lzy',
// database: 'mytest',
// },
// db2: {
// host: 'localhost',
// port: '3307',
// user: 'root',
// password: '123456',
// database: 'api_gateway',
// }
// },
// //所有数据库配置默认
// default: {},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};

config.cors = {
// 任何地址都可以访问
origin: "*",
// 指定地址才可以访问
// origin: 'http://localhost:8080',
allowMethods: 'GET,PUT,POST,DELETE',
allowHeaders: 'Authorization,Content-Type',
// cookie跨域配置
credentials: true
}

config.jwt = {
secret: "blank_lzy",
expiredIn: '1d'
}
return {
...config,
...userConfig,
};
}

plugin.js

中间件

洋葱模型

  1. // 在app/middleware/checkToken.js 1.编写
    function checkToken(options) {
        return async function (ctx, next) { 
            
            const decode = ctx.app.jwt.verify(token, ctx.app.config.jwt.secret)
            await next()
            ...
        }
    }
    //暴露出去
    module.exports = checkToken
    
    1
    2
    3
    4
    5
    6
    7
    8

    2. ```js
    // 在config.default.js 2.注册
    // 元素顺序是中间件的执行顺序
    config.middleware = ['checkToken']
    config.checkToken: {
    ... //配置
    }
  2. // 在 router.js 3.使用中间件
    router.resources('students','/students',app.middleware.checkToken(), controller.students)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    > 1. options : 是 app.config.checkToken
    > 2. 使用中间件时可以传递参数`app.middleware.checkToken({expiredIn:'7d'}) ` 被`options`接收
    > 3. 中间件里怎么用插件: `ctx.app.jwt`

    ### 中间件里的ctx

    可以看到和控制器里this里的ctx一样

    ```json
    {
    request,
    response,
    app,
    originalUrl,
    req,
    res,
    socket
    }

项目打包发布

  1. npm run build
    #	把dist内的文件都复制到服务器public目录下
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    2. 我们要访问的首页是`localhost:7001/public/index.html` ,但是相关打包文件的请求地址却是`http://localhost:7001/js/chunk-vendors.3c79a5b3.js` 会报404,因为文件在`... :7001/public/js/...`

    ```js
    // config.default.js
    const path = require('path')
    //设置静态文件路径
    config.static = {
    prefix: '/',
    dir: path.join(appInfo.baseDir, 'app/public')
    }
  2. 访问地址变成了localhost:7001/index.html

服务器运行方式除了 npm run dev 还有 npm start

nunjucks插件模板引擎

  1. npm i --save egg-view-nunjucks
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    2. 在plugin.js 和 config.default.js 中配置

    ```js
    //plugin.js
    module.exports = {
    nunjucks: {
    enable: true,
    package: 'egg-view-nunjucks'
    }
    };

    //config.default.js
    module.exports = appInfo => {
    ...
    config.view = {
    defaultViewEngine: 'nunjucks',
    // mapping: {
    // '.tpl': 'nunjucks'
    // }
    }
    }
  2. 在 /app/view 下创建index.html

  3. 在controller 下某个控制器

    1
    await ctx.render('index',{params: '参数'}) //启用模板, 传参给模板

cors跨域插件

  1. npm i --save egg-cors
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    2. ```js
    //plugin.js
    cors: {
    enable: true,
    package: 'egg-cors'
    }

    //config.default.js
    config.cors = {
    // 任何地址都可以访问
    origin:"*",
    // 指定地址才可以访问
    // origin: 'http://localhost:8080',
    allowMethods: 'GET,PUT,POST,DELETE',
    allowHeaders: 'Authorization,Content-Type',
    // cookie跨域配置
    credentials: true
    }

Json Web Token插件

  1. npm i --save egg-jwt
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    2. ```js
    //plugin.js
    jwt: {
    enable: true,
    package: 'egg-jwt'
    }

    //config.default.js
    config.jwt = {
    secret: 'private_key'
    }
  2. //使用
    //1. 签名
    let token = this.app.jwt.sign(userInfo, this.app.config.jwt.secret, { expiresIn: '1d'})
    //2. 解密
    let decode = this.app.jwt.verify(token, this.app.config.jwt.secret)
    

当token错误或过期,verify会直接报错,推荐用try-catch包裹起来