原理

基础使用

https://eggjs.org/zh-cn/intro/quickstart.htm

安装

  1. mkdir egg-demo
  2. cd egg-demo
  3. npm i
  4. npm run dev
  5. 访问http://127.0.0.1:7001

添加视图

  1. // 添加路由
  2. router.get('/stu', controller.stu.index);
  3. // app/controller/stu.js
  4. class StuController extends Controller {
  5. async index() {
  6. const { ctx } = this;
  7. ctx.body = '<h1>hello, Lucy</h1>';
  8. }
  9. }
  10. // 访问 http://127.0.0.1:7001/stu

访问静态资源

创建/public/index.html, 并访问http://127.0.0.1:7001/public/index.html

路由控制

控制器:

  1. 直接相应数据/渲染模板
  2. 接受用户的输入
  3. 与路由建立对应关系

路由:

  1. 获取query参数
  2. 获取params参数

获取query参数

  1. class StuController extends Controller {
  2. async index() {
  3. const { ctx } = this;
  4. const query = ctx.request.query;
  5. ctx.body = `this is page: ${query.page}`;
  6. }
  7. }
  8. // 访问 http://127.0.0.1:7001/stu?page=3
  9. // this is page: 3

获取params参数 (需要修改路由)

  1. // 添加路由
  2. router.get('/stu/:page', controller.stu.getPage);
  3. // 控制器添加方法
  4. async getPage() {
  5. const { ctx } = this;
  6. const params = ctx.params;
  7. ctx.body = `this is page: ${params.page}`;
  8. }
  9. // 访问 http://127.0.0.1:7001/stu/9
  10. // this is page: 9

允许伪造访问

image.png

  1. // config/config.default.js
  2. config.security = {
  3. csrf: {
  4. enable: false,
  5. },
  6. };

RESTful风格

image.png
https://eggjs.org/en/basics/router.html#restful-style-url-definition
路由修改为

  1. // before
  2. router.get('/stu', controller.stu.index);
  3. router.get('/stu/new', controller.stu.new);
  4. router.get('/stu/:id', controller.stu.show);
  5. router.post('/stu', controller.stu.create);
  6. // after
  7. 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

  1. 'use strict';
  2. const Controller = require('egg').Controller;
  3. const students = [
  4. { id: 1, name: 'Jack'},
  5. { id: 2, name: 'Lcuy'},
  6. ];
  7. class StuController extends Controller {
  8. async index() {
  9. const { ctx } = this;
  10. ctx.body = students;
  11. }
  12. async new() {
  13. const { ctx } = this;
  14. ctx.body = `<form action="/stu" method="post" class="form-example">
  15. <div class="form-example">
  16. <label for="name">Enter your name: </label>
  17. <input type="text" name="name" id="name" required>
  18. </div>
  19. <div class="form-example">
  20. <input type="submit" value="新增">
  21. </div>
  22. </form>`
  23. }
  24. async show() {
  25. const { ctx } = this;
  26. const params = ctx.params;
  27. ctx.body = students[params.id];
  28. }
  29. async create() {
  30. const { ctx } = this;
  31. const { body } = ctx.request;
  32. // console.log(body);
  33. students.push({
  34. id: students.length,
  35. ...body
  36. })
  37. ctx.body = '创建成功!'
  38. ctx.redirect('/stu');
  39. }
  40. }
  41. module.exports = StuController;

插件

允许跨域 egg-cors

  1. 安装 yarn add egg-cors
  2. 配置 ``` // config/plugin.js cors: { enable: true, package: ‘egg-cors’, },

// config/config.default.js config.cors = { origin: ‘*’, allowMethods: ‘GET,HEAD,PUT,POST,DELETE,PATCH’, };

  1. <a name="bPi8m"></a>
  2. #### nunjucks模版插件 egg-view-nunjucks
  3. 1. 安装
  4. 2. 配置插件
  5. 3. 创建模版文件, 控制器中使用render方法
  6. 配置插件

// egg-demo/config/plugin.js nunjucks: { enable: true, package: ‘egg-view-nunjucks’, // 注意 },

// egg-demo/config/config.default.js config.view = { defaultViewEngine: ‘nunjucks’, };

  1. 创建模版文件app/view/home.html 控制器中使用render方法

async index() { const { ctx } = this; // ctx.body = ‘

hello, Lucy

‘; await ctx.render(‘home.html’); }

  1. 模版注入数据

// controller.home.index
await ctx.render(‘home.html’, {names: [‘Jack’, ‘Lucy’]});

// view/home.html

学生列表

    {% for item in names %}
  1. {{ item }}
  2. {% endfor %}

  1. <a name="MMOMT"></a>
  2. ### 用户登录(插件: egg-jwt)
  3. - cookie 与 session
  4. - JWT (Json Web Token)
  5. session保持用户登陆状态,
  6. - 未登陆/注销 ,跳转至登陆页
  7. - 登陆, 跳至首页
  8. token; 加密的标识, 客户端带token向服务器发送请求, 以证明自己的身份
  9. 1. 安装egg-jwt yarn add egg-jwt
  10. 2. 配置插件
  11. 3. 用法
  12. 配置插件

// config/plugin.js jwt: { enable: true, package: ‘egg-jwt’, },

// config/config.default.js config.jwt = { secret: ‘123456’, };

  1. ![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

  1. ![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 }

  1. <a name="h3vPQ"></a>
  2. ### 中间件(验证token并拦截)
  3. middleware
  4. 1. 目录中创建js文件
  5. 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无效’ }; } } }

  1. 使用中间件, 倒数第二个参数

router.resources(‘stu’, ‘/stu’, app.middleware.checktoken(), controller.stu);

  1. 服务端:
  2. 1. 登陆, 返回token
  3. 2. 接口(非登陆), 添加中间件验证token 无效token拦截
  4. 客户端:
  5. 1. 登陆后, 本地存放token
  6. 2. 接口头部添加token
  7. 3. token拦截, 跳转至登陆页
  8. 1. 本地识别, 跳转前检查**是否存在token**
  9. 2. 接口返回拦截, **无效token**
  10. <a name="kPiob"></a>
  11. #### 辅助工具postman
  12. <a name="mMrB2"></a>
  13. ### 持久化
  14. 狭义的理解_: _持久化__仅仅指把域对象永久保存到数据库中;广义的理解_,_“持久化”包括和数据库相关的各种操作。<br />意义:
  15. - 通过持久化技术可以减少访问数据库数据次数,增加应用程序执行速度;
  16. - 代码重用性高,能够完成大部分数据库操作;
  17. - 松散耦合,使持久化不依赖于底层数据库和上层业务逻辑实现,更换数据库时只需修改配置文件而不用修改代码
  18. 需求:<br />使用mysql数据库, sequelizeORM框架)管理数据层的代码
  19. <a name="Wqi7a"></a>
  20. #### ORM(对象关系映射, Object Relational Mapping)
  21. 1. 将数据从对象的形式, 转换成表格的形式
  22. 2. sequelize是一个基于nodeorm框架
  23. 3. 通过egg-sequelize 直接使用sequelize提供的方法操作数据库
  24. - [ ] 服务
  25. <a name="PTvur"></a>
  26. ### 项目部署
  27. 前端打包放置到public文件夹下
  28. <a name="LYrEo"></a>
  29. #### 启动 & 终止

npm run start npm run stop

  1. <a name="gTqDa"></a>
  2. ### Docker 部署项目
  3. <a name="FFLFf"></a>
  4. ## 一些辅助工作
  5. <a name="atHpg"></a>
  6. ### 创建数据库
  7. <a name="XxrEa"></a>
  8. ### Vue工程
  9. <a name="t3k9l"></a>
  10. #### 配置代理
  11. <a name="MN6Sr"></a>
  12. #### 或者配置全局环变量

// .env.development VUE_APP_BASE_API = “http://127.0.0.1:7001

// 读取 process.env.VUE_APP_BASE_API

  1. <a name="SShUw"></a>
  2. #### 封装axios

// stu-vue/src/utils/request.js

// main.ts Vue.prototype.$request = request ```

实践CURD

高级使用

配置RPC