原理
基础使用
https://eggjs.org/zh-cn/intro/quickstart.htm
安装
mkdir egg-demo
cd egg-demo
npm i
npm run dev
访问http://127.0.0.1:7001
添加视图
// 添加路由
router.get('/stu', controller.stu.index);
// app/controller/stu.js
class StuController extends Controller {
async index() {
const { ctx } = this;
ctx.body = '<h1>hello, Lucy</h1>';
}
}
// 访问 http://127.0.0.1:7001/stu
访问静态资源
创建/public/index.html, 并访问http://127.0.0.1:7001/public/index.html
路由控制
控制器:
- 直接相应数据/渲染模板
- 接受用户的输入
- 与路由建立对应关系
路由:
- 获取query参数
- 获取params参数
获取query参数
class StuController extends Controller {
async index() {
const { ctx } = this;
const query = ctx.request.query;
ctx.body = `this is page: ${query.page}`;
}
}
// 访问 http://127.0.0.1:7001/stu?page=3
// this is page: 3
获取params参数 (需要修改路由)
// 添加路由
router.get('/stu/:page', controller.stu.getPage);
// 控制器添加方法
async getPage() {
const { ctx } = this;
const params = ctx.params;
ctx.body = `this is page: ${params.page}`;
}
// 访问 http://127.0.0.1:7001/stu/9
// this is page: 9
允许伪造访问
// config/config.default.js
config.security = {
csrf: {
enable: false,
},
};
RESTful风格
https://eggjs.org/en/basics/router.html#restful-style-url-definition
路由修改为
// before
router.get('/stu', controller.stu.index);
router.get('/stu/new', controller.stu.new);
router.get('/stu/:id', controller.stu.show);
router.post('/stu', controller.stu.create);
// after
router.resources('stu', '/stu', controller.stu);
查询(详情)/新增
查询
http://127.0.0.1:7001/stu
http://127.0.0.1:7001/stu/1
新增页
http://127.0.0.1:7001/stu/new
'use strict';
const Controller = require('egg').Controller;
const students = [
{ id: 1, name: 'Jack'},
{ id: 2, name: 'Lcuy'},
];
class StuController extends Controller {
async index() {
const { ctx } = this;
ctx.body = students;
}
async new() {
const { ctx } = this;
ctx.body = `<form action="/stu" method="post" class="form-example">
<div class="form-example">
<label for="name">Enter your name: </label>
<input type="text" name="name" id="name" required>
</div>
<div class="form-example">
<input type="submit" value="新增">
</div>
</form>`
}
async show() {
const { ctx } = this;
const params = ctx.params;
ctx.body = students[params.id];
}
async create() {
const { ctx } = this;
const { body } = ctx.request;
// console.log(body);
students.push({
id: students.length,
...body
})
ctx.body = '创建成功!'
ctx.redirect('/stu');
}
}
module.exports = StuController;
插件
允许跨域 egg-cors
- 安装 yarn add egg-cors
- 配置 ``` // config/plugin.js cors: { enable: true, package: ‘egg-cors’, },
// config/config.default.js config.cors = { origin: ‘*’, allowMethods: ‘GET,HEAD,PUT,POST,DELETE,PATCH’, };
<a name="bPi8m"></a>
#### nunjucks模版插件 egg-view-nunjucks
1. 安装
2. 配置插件
3. 创建模版文件, 控制器中使用render方法
配置插件
// egg-demo/config/plugin.js nunjucks: { enable: true, package: ‘egg-view-nunjucks’, // 注意 },
// egg-demo/config/config.default.js config.view = { defaultViewEngine: ‘nunjucks’, };
创建模版文件app/view/home.html, 控制器中使用render方法
async index() { const { ctx } = this; // ctx.body = ‘
hello, Lucy
‘; await ctx.render(‘home.html’); }
模版注入数据
// controller.home.index
await ctx.render(‘home.html’, {names: [‘Jack’, ‘Lucy’]});
// view/home.html
学生列表
-
{% for item in names %}
- {{ item }} {% endfor %}
<a name="MMOMT"></a>
### 用户登录(插件: egg-jwt)
- cookie 与 session
- JWT (Json Web Token)
session保持用户登陆状态,
- 未登陆/注销 ,跳转至登陆页
- 登陆, 跳至首页
token; 加密的标识, 客户端带token向服务器发送请求, 以证明自己的身份
1. 安装egg-jwt yarn add egg-jwt
2. 配置插件
3. 用法
配置插件
// config/plugin.js jwt: { enable: true, package: ‘egg-jwt’, },
// config/config.default.js config.jwt = { secret: ‘123456’, };
![image.png](https://cdn.nlark.com/yuque/0/2021/png/601538/1617715112198-fd57f655-f3ac-480b-85f1-8553ce4b3b22.png#height=223&id=aYgol&margin=%5Bobject%20Object%5D&name=image.png&originHeight=446&originWidth=1132&originalType=binary&size=386145&status=done&style=none&width=566)<br />获取密钥 this.app.jwt.secret<br />读取头部token this.ctx.request.header.token
// 签名 const token = this.app.jwt.sign(‘admin’, ‘secret’) // eyJhbGciOiJIUzI1NiJ9.YWRtaW4.Hq25ihi_FB2DYnhkH9mO7z7nz67xPsE5IfFsUgDhbrU
// 验证 try { const decode = this.app.jwt.verify(token, ‘secret’) } catch() { this.ctx.body = ‘token未能通过验证!’ } // admin
![image.png](https://cdn.nlark.com/yuque/0/2021/png/601538/1617715366616-8c700b3e-6d0b-40d3-b0f9-32dee07ea8b9.png#height=63&id=jvaVe&margin=%5Bobject%20Object%5D&name=image.png&originHeight=126&originWidth=1446&originalType=binary&size=78271&status=done&style=none&width=723)<br />登陆伪代码
const { username, password } = ctx.request.body; if (username == ‘admin’ && password == ‘123456’) { const token = this.app.jwt.sign(username, this.app.jwt.secret) // response-token } else { // response-error }
<a name="h3vPQ"></a>
### 中间件(验证token并拦截)
middleware
1. 目录中创建js文件
2. 使用中间件
// app/middleware/checktoken.js
function checktoken() { return async function(ctx, next) { try { let token = ctx.request.header.token; console.log(‘middleware’, token, ctx.request); let username = ctx.app.jwt.verify(token, ctx.app.config.jwt.secret) if (username) { await next(); } } catch (e) { ctx.body = { code: 400, msg: ‘token无效’ }; } } }
使用中间件, 倒数第二个参数
router.resources(‘stu’, ‘/stu’, app.middleware.checktoken(), controller.stu);
服务端:
1. 登陆, 返回token
2. 接口(非登陆), 添加中间件验证token, 无效token拦截
客户端:
1. 登陆后, 本地存放token
2. 接口头部添加token
3. token拦截, 跳转至登陆页
1. 本地识别, 跳转前检查**是否存在token**
2. 接口返回拦截, **无效token**
<a name="kPiob"></a>
#### 辅助工具postman
<a name="mMrB2"></a>
### 持久化
狭义的理解_: “_持久化_”_仅仅指把域对象永久保存到数据库中;广义的理解_,_“持久化”包括和数据库相关的各种操作。<br />意义:
- 通过持久化技术可以减少访问数据库数据次数,增加应用程序执行速度;
- 代码重用性高,能够完成大部分数据库操作;
- 松散耦合,使持久化不依赖于底层数据库和上层业务逻辑实现,更换数据库时只需修改配置文件而不用修改代码
需求:<br />使用mysql数据库, sequelize(ORM框架)管理数据层的代码
<a name="Wqi7a"></a>
#### ORM(对象关系映射, Object Relational Mapping)
1. 将数据从对象的形式, 转换成表格的形式
2. sequelize是一个基于node的orm框架
3. 通过egg-sequelize, 直接使用sequelize提供的方法操作数据库
- [ ] 服务
<a name="PTvur"></a>
### 项目部署
前端打包放置到public文件夹下
<a name="LYrEo"></a>
#### 启动 & 终止
npm run start npm run stop
<a name="gTqDa"></a>
### Docker 部署项目
<a name="FFLFf"></a>
## 一些辅助工作
<a name="atHpg"></a>
### 创建数据库
<a name="XxrEa"></a>
### Vue工程
<a name="t3k9l"></a>
#### 配置代理
<a name="MN6Sr"></a>
#### 或者配置全局环变量
// .env.development VUE_APP_BASE_API = “http://127.0.0.1:7001“
// 读取 process.env.VUE_APP_BASE_API
<a name="SShUw"></a>
#### 封装axios
// stu-vue/src/utils/request.js
// main.ts Vue.prototype.$request = request ```