记录一次使用Egg.js快速开发接口

记录一次使用Egg.js快速开发接口

记录一次使用Egg.js快速开发接口

Egg介绍

Egg.js 为企业级框架和应用而生,帮助开发团队和开发人员降低开发和维护成本。

官方文档介绍最详细,有问题先看看官方文档。快速入门官方文档

初始化Egg项目

使用官方脚手架 egg-init 开始项目

  • 脚手架安装:npm i -g egg-init
  • 初始化目录:egg-init egg-first --type=simple
  • 安装项目依赖:cd egg-first && npm i
  • 热部署启动:npm run dev
1
2
3
4
5
6
$ mkdir egg-exam
$ cd egg-exam
$ npm i -g egg-init
$ egg-init egg-first --type=simple
$ cd egg-first && npm i
$ npm run dev

npm run dev后可以打开http://127.0.0.1:7001/看到hi,egg

Egg初始化项目目录结构

[下面是官网对目录结构的解释][https://eggjs.org/zh-cn/basics/structure.html]

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
egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service (可选)
│ | └── user.js
│ ├── middleware (可选)
│ | └── response_time.js
│ ├── schedule (可选)
│ | └── my_task.js
│ ├── public (可选)
│ | └── reset.css
│ ├── view (可选)
│ | └── home.tpl
│ └── extend (可选)
│ ├── helper.js (可选)
│ ├── request.js (可选)
│ ├── response.js (可选)
│ ├── context.js (可选)
│ ├── application.js (可选)
│ └── agent.js (可选)
├── config
| ├── plugin.js
| ├── config.default.js
│ ├── config.prod.js
| ├── config.test.js (可选)
| ├── config.local.js (可选)
| └── config.unittest.js (可选)
└── test
├── middleware
| └── response_time.test.js
└── controller
└── home.test.js

如上,由框架约定的目录:

  • app/router.js 用于配置 URL 路由规则,具体参见 Router
  • app/controller/** 用于解析用户的输入,处理后返回相应的结果,具体参见 Controller
  • app/service/** 用于编写业务逻辑层,可选,建议使用,具体参见 Service
  • app/middleware/** 用于编写中间件,可选,具体参见 Middleware
  • app/public/** 用于放置静态资源,可选,具体参见内置插件 egg-static
  • app/extend/** 用于框架的扩展,可选,具体参见框架扩展
  • config/config.{env}.js 用于编写配置文件,具体参见配置
  • config/plugin.js 用于配置需要加载的插件,具体参见插件
  • test/** 用于单元测试,具体参见单元测试
  • app.jsagent.js 用于自定义启动时的初始化工作,可选,具体参见启动自定义。关于agent.js的作用参见Agent机制

管理数据库连接

Egg-mysql官方教程

1
$ npm i --save egg-mysql

开启插件:

1
2
3
4
5
// config/plugin.js
exports.mysql = {
enable: true,
package: 'egg-mysql',
};

image-20210316180122442

在config.default.js管理数据库连接

image-20210316212248753

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
/* eslint valid-jsdoc: "off" */

'use strict';

/**
* @param {Egg.EggAppInfo} appInfo app info
*/
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 + '_1615888380183_2642';

// add your middleware config here
config.middleware = [];

// add your user config here
const userConfig = {
// myAppName: 'egg',
};
// config/config.${env}.js
exports.mysql = {
clients: {
// clientId, 获取client实例,需要通过 app.mysql.get('clientId') 获取
taobaoBuy: {//硬盘损坏
// host
host: 'localhost',
// 端口号
port: '3306',
// 用户名
user: 'root',
// 密码
password: 'ss123456',
// 数据库名
database: 'taobao_buy',
}
// ...
},
// 所有数据库配置的默认值
default: {
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};

//下面本地调试解决跨域问题
// 配置指定的前端地址
config.cors = {
origin: '*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
// 下面这条加上才能共享跨域session,同时前端ajax请求也要加上响应的参数
credentials: true,
};

config.security = {
// 关闭csrf验证
csrf: {
enable: false,
ignoreJSON: true
},
// 白名单
domainWhiteList: ['*']
};

return {
...config,
...userConfig,
};

};

router层

编码流程:写路由,写对应控制层,写对应服务层。

对应app/router.js。Router 主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系, 框架约定了 app/router.js 文件用于统一所有路由规则。

下面这个URL就是对应接口了。后面可以打开浏览器看接口数据。这里以一个例子解释。

image-20210316212631480

1
2
3
4
5
module.exports = app => {
const { router, controller } = app;
router.get('/api/taobao/findall', controller.taobao.findAll);
};

controller层

控制层编码流程:验证参数,调用服务层,返回数据。

新建controller文件夹,对应app/controller。Controller负责解析用户的输入,处理后返回相应的结果,例如:

  • 在 RESTful 接口中,Controller 接受用户的参数,从数据库中查找内容返回给用户或者将用户的请求更新到数据库中。
  • 在 HTML 页面请求中,Controller 根据用户访问不同的 URL,渲染不同的模板得到 HTML 返回给用户。
  • 在代理服务器中,Controller 将用户的请求转发到其他服务器上,并将其他服务器的处理结果返回给用户。

image-20210316212919022

1
2
3
4
5
6
7
8
9
10
11
12
'use strict';

const Controller = require('egg').Controller;

class HomeController extends Controller {
async findAll() {
const data = await this.service.taobaoTest.findAll();
this.ctx.body = data;
}
}

module.exports = HomeController;

Service层

服务层编码流程:访问持久化层,获取数据,返回格式化数据。

新建service文件夹和taobaoTest.js。这一层主要写业务逻辑的,需要自己对照业务需求编写。参考意义不大。

框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回:

  1. 获取用户通过 HTTP 传递过来的请求参数。
  2. 校验、组装参数。
  3. 调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。
  4. 通过 HTTP 将结果响应给用户。

image-20210316213349069

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Service = require('egg').Service;
class taobaoTestService extends Service {

async findAll() {
const client = this.app.mysql.get('taobaoBuy');
var sql1 = "select time_hour,count(*) as data from tb GROUP BY user_id,time_hour";//改sql语句
const result1 = await client.query(sql1);
let data1=[];
let timeHour=[];
for (let index = 0; index < result1.length; index++) {
data1[index] = result1[index].data;
timeHour[index] = result1[index].time_hour;
}
let json ={
time_hour : timeHour,
data: data1,
}
return json;
}
}

module.exports = taobaoTestService;

最后npm run dev

浏览器打开路由定义的URL看看。可以看到数据出来了。

image-20210316215646710

关于报错

遇到报错呢,先看看报错说的是什么,可以很快定位错误的位置,比如下图,看throw error这里:

image-20210316211619807

对应/egg.router/taobao.js第三行,原因是index没有定义,那么就可以查看一下controller、service里index部分有没有定义了。

又比如:

egg 运行 npm run dev后报错 nodejs.AppWorkerDiedError,可能是数据库连接问题,检查是否能正常连接数据库。账户、密码对不对?

作者

terese

发布于

2021-01-27

更新于

2022-10-05

许可协议