egg是阿里开源的企业级框架,主要设计理念为平衡团队之间的技术差异,专注于提供 Web 开发的核心功能和一套灵活可扩展的插件机制。通过 Egg,团队的架构师和技术负责人可以非常容易地基于自身的技术架构在 Egg 基础上扩展出适合自身业务场景的框架。

Egg 的插件机制有很高的可扩展性,一个插件只做一件事(比如 Nunjucks 模板封装成了 egg-view-nunjucks、MySQL 数据库封装成了 egg-mysql)。Egg 通过框架聚合这些插件,并根据自己的业务场景定制配置,这样应用的开发成本就变得很低。

Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本,开发人员不再是『钉子』,可以流动起来。没有约定的团队,沟通成本是非常高的,比如有人会按目录分栈而其他人按目录分功能,开发者认知不一致很容易犯错。但约定不等于扩展性差,相反 Egg 有很高的扩展性,可以按照团队的约定定制框架。使用 Loader 可以让框架根据不同环境定义默认配置,还可以覆盖 Egg 的默认约定。

官方文档  https://eggjs.org/zh-cn/intro/quickstart.html

主要模块:

一、路由(Router)

app/router.js 里面定义 URL 路由规则

// app/router.js
module.exports = app => {const { router, controller } = app;router.get('/user/:id', controller.user.info);
};

app/controller 目录下面实现 Controller

// app/controller/user.js
class UserController extends Controller {async info() {const { ctx } = this;ctx.body = {name: `hello ${ctx.params.id}`,};}
}

在 Router 定义中, 可以支持多个 Middleware 串联执行
Controller 必须定义在 app/controller 目录中。
一个文件里面也可以包含多个 Controller 定义,在定义路由的时候,可以通过 ${fileName}.${functionName} 的方式指定对应的 Controller。
Controller 支持子目录,在定义路由的时候,可以通过 ${directoryName}.${fileName}.${functionName} 的方式制定对应的 Controller。

路由定义方式:

// app/router.js
module.exports = app => {const { router, controller } = app;router.get('/home', controller.home);router.get('/user/:id', controller.user.page);router.post('/admin', isAdmin, controller.admin);router.post('/user', isLoginUser, hasAdminPermission, controller.user.create);router.post('/api/v1/comments', controller.v1.comments.create); // app/controller/v1/comments.js
};

二、控制器(Controller)

Controller 负责解析用户的输入,处理后返回相应的结果,例如

在 RESTful 接口中,Controller 接受用户的参数,从数据库中查找内容返回给用户或者将用户的请求更新到数据库中。
在 HTML 页面请求中,Controller 根据用户访问不同的 URL,渲染不同的模板得到 HTML 返回给用户。
在代理服务器中,Controller 将用户的请求转发到其他服务器上,并将其他服务器的处理结果返回给用户。
框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回:

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

参数获取:

Query String 方式

// app/router.js
module.exports = app => {app.router.get('/search', app.controller.search.index);
};// app/controller/search.js
exports.index = async ctx => {ctx.body = `search: ${ctx.query.name}`;
};

参数命名方式

// app/router.js
module.exports = app => {app.router.get('/user/:id/:name', app.controller.user.info);
};// app/controller/user.js
exports.info = async ctx => {ctx.body = `user: ${ctx.params.id}, ${ctx.params.name}`;
};

返回数据:

ctx.response.body(简写为ctx.body),不建议使用简写语法,因为会造成跟ctx.request.body的混淆误解作为企业级应用开发,要考虑到新人接手的可读性和学习效率。

重定向:

框架通过 security 插件覆盖了 koa 原生的 ctx.redirect 实现,以提供更加安全的重定向。

ctx.redirect(url) 如果不在配置的白名单域名内,则禁止跳转。
ctx.unsafeRedirect(url) 不判断域名,直接跳转,一般不建议使用,明确了解可能带来的风险后使用。
用户如果使用ctx.redirect方法,需要在应用的配置文件中做如下配置:

// config/config.default.js
exports.security = {domainWhiteList:['.domain.com'],  // 安全白名单,以 . 开头
};

若用户没有配置 domainWhiteList 或者 domainWhiteList数组内为空,则默认会对所有跳转请求放行,即等同于ctx.unsafeRedirect(url)

三、服务(Service)

Service 就是在复杂业务场景下用于做业务逻辑封装的一个抽象层,提供这个抽象有以下几个好处:

保持 Controller 中的逻辑更加简洁。
保持业务逻辑的独立性,抽象出来的 Service 可以被多个 Controller 重复调用。
将逻辑和展现分离,更容易编写测试用例,测试用例的编写具体可以查看这里。

定义 Service

// app/service/user.js
const Service = require('egg').Service;class UserService extends Service {async find(uid) {const user = await this.ctx.db.query('select * from user where uid = ?', uid);return user;}
}module.exports = UserService;

Service ctx 详解

为了可以获取用户请求的链路,我们在 Service 初始化中,注入了请求上下文, 用户在方法中可以直接通过 this.ctx 来获取上下文相关信息。关于上下文的具体详解可以参看 Context, 有了 ctx 我们可以拿到框架给我们封装的各种便捷属性和方法。比如我们可以用:

this.ctx.curl 发起网络调用。
this.ctx.service.otherService 调用其他 Service。
this.ctx.db 发起数据库调用等, db 可能是其他插件提前挂载到 app 上的模块。

// app/router.js
module.exports = app => {app.router.get('/user/:id', app.controller.user.info);
};// app/controller/user.js
const Controller = require('egg').Controller;
class UserController extends Controller {async info() {const { ctx } = this;const userId = ctx.params.id;const userInfo = await ctx.service.user.find(userId);ctx.body = userInfo;}
}
module.exports = UserController;// app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {// 默认不需要提供构造函数。// constructor(ctx) {//   super(ctx); 如果需要在构造函数做一些处理,一定要有这句话,才能保证后面 `this.ctx`的使用。//   // 就可以直接通过 this.ctx 获取 ctx 了//   // 还可以直接通过 this.app 获取 app 了// }async find(uid) {// 假如 我们拿到用户 id 从数据库获取用户详细信息const user = await this.ctx.db.query('select * from user where uid = ?', uid);// 假定这里还有一些复杂的计算,然后返回需要的信息。const picture = await this.getPicture(uid);return {name: user.user_name,age: user.age,picture,};}async getPicture(uid) {const result = await this.ctx.curl(`http://photoserver/uid=${uid}`, { dataType: 'json' });return result.data;}
}
module.exports = UserService;

常见问题:

启动服务:

npm run dev

PM2 启动:

egg不推荐使用 PM2 启动,但仍然可以使用。

在项目根目录定义启动文件:

// server.js
const egg = require('egg');const workers = Number(process.argv[2] || require('os').cpus().length);
egg.startCluster({workers,baseDir: __dirname,
});
pm2 start server.js

修改端口:

/config/config.default.js

  config.cluster = {listen: {path: '',port: 7002,hostname: '0.0.0.0',},};

csrf 报错:

Egg 内置的 egg-security 插件默认对所有『非安全』的方法,例如 POST,PUT,DELETE 都进行 CSRF 校验。

请求遇到 csrf 报错通常是因为没有加正确的 csrf token 导致,如不需要csrf防范,在/config/config.default.js里设置:

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

如需csrf校验,阅读 安全威胁 CSRF 的防范

开发示例:

//app/router.js
'use strict';
module.exports = app => {const { router, controller } = app;router.get('/', controller.home.index);router.get('/Title1', controller.test.Title1);router.post('/Title2', controller.test.Title2);
};
//app/controller/test.js
'use strict';
const Controller = require('egg').Controller;
class TestController extends Controller {async Title1() {const query = this.ctx.query;const adds = query.l1 + '  ' + query.l2;const dataList = {list: [{ id: 1, title: 'this is news 1', url: '/news/1', l1: query.l1, sum: adds },{ id: 2, title: 'this is news 2', url: '/news/2', l2: query.l2, sum: adds }],};this.ctx.response.body = dataList;}async Title2() {const adds = this.ctx.request.body.l1 + this.ctx.request.body.l2;const dataList = {list: [{ id: 1, title: 'this is news 1', url: '/news/1', sum: adds },{ id: 2, title: 'this is news 2', url: '/news/2', sum: adds }],};this.ctx.response.body = dataList;}
}
module.exports = TestController;

node.js——阿里企业级服务框架Egg搭建相关推荐

  1. Pomelo:网易开源基于 Node.js 的游戏服务端框架

    Pomelo 是基于 Node.js 的高性能.分布式游戏服务器框架.它包括基础的开发框架和相关的扩展组件(库和工具包),可以帮助你省去游戏开发枯燥中的重复劳动和底层逻辑的开发.Pomelo 不但适用 ...

  2. node.js安装express(零起点搭建本地测试服务器)- 教程篇

    (含图文教程.代码对比,等)node.js安装express(零起点搭建本地测试服务器)- 教程篇 原教程 · 参考地址 执行step3之后,结果截图 · 如下图2 : 之后,执行step4,截图如下 ...

  3. Node.js + Consul 实现服务注册、健康检查、配置中心

    Node.js + Consul 实现服务注册.健康检查.配置中心 在这篇文章中: 初始化 Consul 客户端 服务注册与健康检查 配置Consul管理控制台 服务配置中心实现 在Nodejs中进行 ...

  4. mac环境搭建node.js并启服务

    1.node官网下载并安装(https://nodejs.org/en/) 2.node -v  //查看版本 3.安装成功后后在Finder中打开用户目录(就是Mac管理员,点开侧栏创建一个Js文件 ...

  5. 为一个 iOS 应用编写一个简单的 Node.js/MongoDB Web 服务

    原文链接:https://github.com/nixzhu/dev-blog/blob/master/2014-04-21-write-a-simple-nodejs-mongodb-web-ser ...

  6. 基于 Node.js 爬虫的数据 API,搭建一套属于自己的 API 数据

    SpliderApi https://github.com/ecitlm/Spl... 基于nodejs 的爬虫 API接口项目,包括前端开发日报.知乎日报.前端top框架排行.妹纸福利.搞笑视频/ ...

  7. node mysql做项目视频教程_2018最新 自学Node/Node.js/Nodejs视频教程 后端框架Express项目实战...

    课程简介 这是一套完整零基础学习Node.js全栈开发的视频教程. 教程到的内容包括: (1)JavaScript基础(基本语法.数据类型.操作符.语句.对象.Math对象等) (2)Node.js基 ...

  8. node.js创建WebSocket服务,并使用原生js ES6完成对WebSocket数据交互

    注意,前情提示: 本代码基于<Node.js(nodejs)对本地JSON文件进行增.删.改.查操作(轻车熟路)> 传送门Node.js(nodejs)对本地JSON文件进行增.删.改.查 ...

  9. 将node.js程序作为服务,并在windows下开机自动启动(使用forever)

    手上项目中有一块服务是用node.js实现的,运行环境是windows server 2008 R2,刚开始着手实现这块功能的时候时间很紧迫,随便写了个console程序就部署上去了--启动方式就是在 ...

最新文章

  1. 解密FFmpeg播放track mode控制
  2. SketchUp(草图大师) 2019 安装教程
  3. 关于印发《会计电算化管理办法》等规章的通知
  4. Web前端必备-Nginx知识汇总
  5. Java黑皮书课后题第3章:*3.32(几何:点的位置)给定一个从点p0(x0,y0)到p1(x1,y1)的有向线段,可以用以下公式判定定点p2(x2, y2)是在线段的左侧、右侧,或者在该线段上
  6. 暑假做题记录【实时更新】
  7. hive启动mapreduce任务后,被killed
  8. php 查询and or,php – SQL查询多个AND和OR不起作用
  9. 学会拒绝别人的6个技巧_多少人败在不懂拒绝上!牢记10个高情商拒绝技巧,人生越来越顺...
  10. 今天的快乐从何而来的飞鸽传书
  11. Python数据分析-初识numpy、pandas、scipy、matplotlib和Scikit-Learn等数据处理库
  12. php框架大全图解_PHP框架汇总 - 鱼煎的个人空间 - OSCHINA - 中文开源技术交流社区...
  13. linux svn 安装信息,linux 下安装 subversion(svn) 客户端
  14. 递归算法设计 —— 选择排序和冒泡排序
  15. 敏捷开发免费管理工具——火星人预览(四)
  16. 解决jquery中全选点击第二次不生效的问题与分析
  17. tomcat按日期分割日志(官网文档推荐实现)
  18. 用户手册 (V4.0 版)
  19. 基于pytorch的花卉识别小程序
  20. Springboot毕业设计毕设作品,黑白图片大全和AI智能上色系统

热门文章

  1. 60 SD配置-科目分配-分配总帐科目
  2. C语言 memcpy函数(增加dst 从第一字节拷贝判断)的内部简单实现方式
  3. usb连接不上 艾德克斯电源_STM32F7 电源控制器(PWR)
  4. QT:不停的提示“文件已改变”
  5. OpenCV Mat主要用法(2)_MatExpr
  6. pix2pix, CycleGAN和pix2pixHD(没有公式,容易理解)
  7. 边缘计算:万物互联时代新型计算模型
  8. android 搭建短信平台,Android 短信SDK集成文档 | Mob文档中心
  9. c语言位向量机伞_一文读懂C语言精华-指针变量和指向指针的指针
  10. 解决Vue报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location