上一篇介绍了 前端调用数据库,使用可视化DBevaer创建数据
手把手的教程,相信大家都学会了操作Dbeaver ,但是可能对于Egg.js这个框架还很生疏,这篇文章就带大家快速学习Egg.js,上手功能开发
Egg.js介绍
Egg.js奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本
Egg.js是阿里团队开发的,中文文档内容很丰富,使用过程中遇到问题,可以很方便地找到对应的内容。
最重要的是Egg 是为企业级框架和应用而生 ,奉行『约定优于配置 』,按照统一的约定进行应用开发,学习成本低,能够快速上手
初始化项目
直接使用脚手架,只需几条简单指令,即可快速生成项目
js
mkdir egg-example && cd egg-example
npm init egg --type=simple
npm i
默认选中第一个模板,然后一路回车
Egg.js 目录结构如下:
js
egg-project
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service (可选)
│ | └── user.js
│ ├── middleware (可选)
│ | └── response_time.js
│ ├── schedule (可选)
│ | └── my_task.js
│ ├── public (可选)
│ | └── reset.css
├── config
| ├── plugin.js
| ├── config.default.js
│ ├── config.prod.js
└── test
├── middleware
| └── response_time.test.js
└── controller
└── home.test.js
其中最主要以及我们需要用到的文件有以下几项
app/router.js
用于配置 URL 路由规则app/controller/**
用于解析用户的输入,处理后返回相应的结果app/service/**
用于编写业务逻辑层,可选,建议使用app/middleware/**
用于编写中间件,可选config/config.{env}.js
用于编写配置文件app.js
和agent.js
用于自定义启动时的初始化工作,可选,具体参见启动自定义
js
npm run dev
在浏览器输入 http://127.0.0.1:7001/ 我们就可以看到 egg的页面了
页面上显示 "hi,egg" 接下来就带大家逐层分析,egg框架
js
egg-project
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service (可选)
│ | └── user.js
│ ├── middleware (可选)
│ | └── response_time.js
│ ├── schedule (可选)
│ | └── my_task.js
│ ├── public (可选)
│ | └── reset.css
├── config
| ├── plugin.js
| ├── config.default.js
│ ├── config.prod.js
└── test
├── middleware
| └── response_time.test.js
└── controller
└── home.test.js
router路由
app/router.js
用来配置路由
主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系
框架约定了 app/router.js
文件用于统一所有路由规则。通过统一的配置,可以避免路由规则逻辑散落在多个地方,从而出现未知的冲突,集中在一起我们可以更方便的来查看全局的路由规则。
比如上述初始化代码中,执行npm run dev
启动项目之后,可以直接在浏览器中访问启动的端口 + 路径
,默认是 http://localhost:7001/
,根据路由配置的规则,去访问对应的内容
app/controller
文件夹又是干什么的呢?
Controller 控制层
app/controller/
的文件就是控制层,它里面的每一个文件都可以看成一个控制器,负责解析用户的输入,处理后返回相应的结果
主要作用:
- 与 路由router 建立对应关系
- 接受用户输入request,解析用户上传的数据,处理后返回相应的结果response( 是业务中唯一和HTTP交互的地方 )
- 直接响应数据或渲染模板
我们可以称 controller 文件夹 为控制层,它里面每个文件可以叫做控制器
在浏览器输入rul,router就拿着对应的/
路由去找控制器的方法
比如说:在浏览器输入 http://localhost:7001/
,然后就会根据路由 调用controller控制层里home控制器的 方法来处理请求
仿写是学习和理解新知识的最好方式,那我们就写一个小需求:将用户的名字显示到页面上
第一步:在home控制器里写一个方法,用来获取地址参数
在home.js文件里新增一个showName 方法:获取参数,并展示到页面上
js
'use strict';
const { Controller } = require('egg');
class HomeController extends Controller {
async index() {
const { ctx } = this;
ctx.body = 'hi, egg';
}
async showName() {
const { ctx } = this;
const { name } = ctx.query;
ctx.body = name;
}
}
module.exports = HomeController;
第二步:我们在路由上新增一个用户的 /user
路由,调用控制器下的showName方法
js
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/user', controller.home.showName);
};
接下来在浏览器里输入 http://127.0.0.1:7001/user?name=董员外
Controller 类 的this 上会有如下属性:
- app: 是当前应用 Application对象的实例,通过它我们可以拿到框架提供的全局对象和方法。
- ctx: 当前请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法。
middleware中间件
app/middleware/**
用于编写中间件,在路由配置里设置了中间件的路由,每次请求命中后,都要过一层中间件,再去调用控制器
中间件在 Egg.js 中具有以下作用:
- 控制请求流程 :中间件可以控制请求的流程 ,决定是否继续向下传递给下一个中间件或控制器,或者提前结束请求。这对于权限校验、路由拦截等场景非常有用。
- 处理公共逻辑 :中间件可以用于处理一些公共的逻辑,例如身份验证、日志记录、异常处理等。通过将这些逻辑封装为中间件,可以避免在每个路由处理函数中重复编写相同的代码,使代码更加简洁和可维护。
- 修改请求和响应:中间件可以在请求到达控制器之前或响应发送给客户端之前对请求和响应进行修改。例如,可以在中间件中添加一些自定义请求头、修改请求参数、对响应进行压缩等操作。
service
app/service/**
Service是中间件 中抽离出来操作数据等作用的逻辑层,可以使Controller保持简洁,可以在多个Controller中重复调用
简单来说,Service 就是在复杂业务场景下用于做业务逻辑封装的一个抽象层
具有以下作用:
- 将逻辑和展现分离,处理复杂的数据,比如要展现的信息需要从数据库获取,还要经过一定的规则计算,才能返回用户显示。或者计算完成后,更新到数据库。
- 第三方服务的调用,比如 GitHub 信息获取等。
- 保持业务逻辑的独立性,抽象出来的 Service 可以被多个 Controller 重复调用。
在开发项目时,连接数据库和操作数据库的方法写在这里
config配置文件
config/***
文件下都是用于编写配置文件
Egg框架提供了强大且可扩展的配置功能,可以自动合并应用、插件、框架的配置,按顺序覆盖,且可以根据环境维护不同的配置。合并后的配置可直接从 app.config
获取。
config.default.js
为默认的配置文件,所有环境都会加载这个配置文件,一般也会作为开发环境的默认配置文件。
在开发项目时,数据库的配置和跨域配置都写在这里
上面的操作都是通过 GET 接口来进行一些操作,处理数据;但是有一些操作需要使用 POST方法进行提交数据,下面我就演示一下在Egg中如何使用POST接口
POST提交数据
在控制器app/controller/home.js
里添加一个 add方法
从请求参数里获取 title参数,然后把他显示到页面上
js
async add() {
const { ctx } = this;
const { title } = ctx.request.body;
ctx.body = {
title,
};
}
再在路由app/router.js
里添加一个/add的路由,当请求这个路由时就调用控制器的add方法
js
module.exports = app => {
// ...
router.post('/add', controller.home.add);
};
因为通过浏览器无法手动发起 POST
请求,所以就需要postman工具进行请求,下面我就演示一下怎么使用 postman
打开postman后新增一个 http://127.0.0.1:7001/add 的 POST请求的接口
请求设置如下,添加title 参数
点击发送后我们可以看到接口报403错误,而且控制台也会有报错
这是因为浏览器的安全策略机制,你请求的 POST
或 GET
接口是非本地计算机(别人的电脑),或者使用 Postman
发起请求,浏览器出于安全考虑,禁止非允许的接口请求。
解决方法就是需要给服务器设置白名单,允许接口访问
在config/config.default.js
配置白名单,* 表示全部允许请求:
js
// 在const config = exports = {};添加如下代码
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: [ '*' ], // 配置白名单
};
然后重新启动服务,再次点击 Send 就可以正常发送请求了