记录一次使用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
[下面是官网对目录结构的解释][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.js
和 agent.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', };
在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 /* 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就是对应接口了。后面可以打开浏览器看接口数据。这里以一个例子解释。
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 将用户的请求转发到其他服务器上,并将其他服务器的处理结果返回给用户。
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 方法处理业务,得到业务结果后封装并返回:
获取用户通过 HTTP 传递过来的请求参数。
校验、组装参数。
调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。
通过 HTTP 将结果响应给用户。
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看看。可以看到数据出来了。
关于报错 遇到报错呢,先看看报错说的是什么,可以很快定位错误的位置,比如下图,看throw error这里:
对应/egg.router/taobao.js第三行,原因是index没有定义,那么就可以查看一下controller、service里index部分有没有定义了。
又比如:
egg 运行 npm run dev后报错 nodejs.AppWorkerDiedError,可能是数据库连接问题,检查是否能正常连接数据库。账户、密码对不对?