前言

“纸上得来终觉浅,绝知此事要躬行。”虽然node一直在断断续续地学,但总是东一榔头西一榔头的,没有一点系统,所以打算写一个项目来串联一下之前的学习成果。

为什么选择Eggjs呢?其实我觉得如果是个人开发或者小型项目Koa就足够轻量与灵活了,但是如果是有过团队开发的经历,就会更注重项目的管理。Eggjs项目相对于Koa我比较看中的有以下几点:

  1. 完善的文档,这意味不管是交接还是项目有新成员加入,直接把官方文档甩出去就行了,而且官方文档同时也是一个很好的学习材料;
  2. Egg 奉行『约定优于配置』。我很中意这个设定,在多人协作的项目中,我们有时候需要花很多功夫来统一不同的编程习惯,比如有人喜欢把公用的方法放到utils/index文件夹中,有的干脆直接建一个utils.js,还有的util不加s的,这些都没有对错之分,但是多人协作项目中会使得项目混乱,难以管理,增加code review的成本。『约定优于配置』则很好地解决了这个问题,大家都统一按官方要求写,有偏差的直接翻文档,没有撕逼了;
  3. 基于Koa,所以Koa的轮子做一下适配就能用,不担心生态问题。

我也是一个node菜鸟,所以这个系列我会按照自己从零实现的步骤去记录整个开发过程。

创建一个Eggjs项目

$ mkdir egg-server && cd egg-server
$ npm init egg --type=simple
$ npm i

OK,项目初始成功了,下面我们的任务是链接数据库。

数据库链接

数据库我选择mysql,毕竟行业主流嘛,这里我们使用Sequelize来管理、操作数据库,Sequelize 是一个基于 promise 的 Node.js ORM,这样你就不用去写一坨一坨的sql语句了。数据库安装这里就不细说了,跟着菜鸟教程安装就好了。安装好并打开数据库。

  1. 安装并配置 egg-sequelize 插件(它会辅助我们将定义好的 Model 对象加载到 app 和 ctx 上)和 mysql2 模块:

    npm install --save egg-sequelize mysql2
  2. app/config/plugin.js中引入插件(egg中引入插件都需要在这个文件中配置):

    sequelize: {
    enable: true,
    package: 'egg-sequelize',
    }
  3. app/config/config.default.js中配置Sequelize的配置项:

    config.sequelize = {
    dialect: 'mysql', // 表示使用mysql
    host: '127.0.0.1', // 连接的数据库主机地址
    port: 3306, // mysql服务端口
    database: 'egg-db', // 数据库名
    username: 'root', // 你的数据库用户名
    password: 'root', // 你的数据库密码
    define: {
    timestamps: true, // 默认添加createdAt,updatedAt,deletedAt时间戳
    paranoid: true, // 设置软删除,删除时不删除数据,而是通过更新deleteAt标识删除
    freezeTableName: true, // 冻结表名,防止建表时表名修改为复数形式
    underscored: false, // 防止驼峰式字段被转为下划线
    },
    // 这里有坑,sequelize用的是UTC时间,我们在东八区,所以要加8
    // https://stackoverflow.com/questions/47367893/sequelize-reads-datetime-in-utc-only
    dialectOptions: {
    dateStrings: true,
    typeCast(field, next) {
    if (field.type === 'DATETIME') {
    return field.string();
    }
    return next();
    },
    },
    timezone: '+8:00',
    };
  4. 创建model

    app文件夹下创建一个model文件夹,所有的model文件都放在这里,现在我们创建一个usermodel,创建以下文件app/model/user.js

    module.exports = (app) => {
    const { STRING, INTEGER } = app.Sequelize;
    const User = app.model.define('user', {
    id: {
    type: INTEGER,
    autoIncrement: true, //自增
    primaryKey: true, //设置为主键
    },
    name: STRING(20),
    password: STRING(100),
    phone: STRING(11),
    email: STRING(30),
    });
    return User;
    };

    OK,现在数据库这块好像都处理的差不多了,那接下来就开些写一下代码,快乐地进行CRUD吧~

  5. 编写controller

    创建app/controller/user.js文件,写入以下内容:

    const Controller = require('egg').Controller;
    
    class UserController extends Controller {
    // 添加user
    async createUser() {
    const params = this.ctx.request.body;
    const user = await this.ctx.model.User.create({
    ...params
    });
    if (user) {
    this.ctx.body = {
    code: 200,
    data: user
    };
    } else {
    this.ctx.throw(500, 'internal server error');
    }
    } // 获取所有的user
    async getUsers() {
    const users = await this.ctx.model.User.findAll();
    this.ctx.body = {
    code: 200,
    data: users
    };
    }
    } module.exports = UserController;
  6. 添加路由

    app/router.js中添加getUserscreateUser的路由,代码如下:

    module.exports = app => {
    const { router, controller } = app;
    router.get('/', controller.home.index);
    + router.post('/createUser', controller.user.createUser);
    + router.get('/getUsers', controller.user.getUsers);
    };
  7. 测试功能

    这个时候我们的代码已经基本完成,请求对应的路由就可以看到对应的数据库变化了,但是我们在请求之前不要忘记在数据库创建对应的数据库和user表哦,不然会报错的,现在可以手动的去创建,后面我们可以借助Sequelize帮我们在项目启动的时候自动创建并更新表。

    一切准备妥当之后,打开Postman来试试吧,通过get请求localhost:7001/getUsers得到以下数据:

    {
    "code": 200,
    "data": []
    }

    这个时候,表是空的,所以查不到,那我们来通过post请求来访问localhost:7001/createUser来创建一条数据:

    {
    "name":"curry",
    "password":"test1234",
    "phone":"13412341234",
    "email":"test@gmai.com"
    }

    然而,这个时候报错了:

    invalid csrf token. See https://eggjs.org/zh-cn/core/security.html#安全威胁csrf的防范

    看一下文档怎么说的:

    CSRF(Cross-site request forgery跨站请求伪造,也被称为 One Click Attack 或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。 CSRF 攻击会对网站发起恶意伪造的请求,严重影响网站的安全。因此框架内置了 CSRF 防范方案。

    这是Eggjs框架的安全策略,我们在开发的时候可以先关掉,在app/onfig/config.default.js中添加以下代码:

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

    改好以后让我们再试一次:

    {
    "code": 200,
    "data": {
    "id": 1,
    "name": "curry",
    "password": "test1234",
    "phone": "13412341234",
    "email": "test@gmai.com",
    "updatedAt": "2020-12-13T07:39:29.990Z",
    "createdAt": "2020-12-13T07:39:29.990Z"
    }
    }

    成功了!打开数据库刷新一下user表看看,已经插入了这条数据,再重新通过get请求localhost:7001/getUsers

    {
    "code": 200,
    "data": [
    {
    "id": 1,
    "name": "curry",
    "password": "test1234",
    "phone": "13412341234",
    "email": "test@gmai.com",
    "createdAt": "2020-12-13 15:39:29",
    "updatedAt": "2020-12-13 15:39:29",
    "deletedAt": null
    }
    ]
    }

    Well done!一番折腾以后终于看到了成果,但这只是开始,后面我们会继续实现用户的注册、登录功能,涉及到用户注册时密码的处理,用户认证等功能。

如何用Eggjs从零开始开发一个项目(1)的更多相关文章

  1. 如何用Eggjs从零开始开发一个项目(2)

    在上一篇文章,我们已经使用Sequelize连接上了数据库,并能进行简单的数据库操作,在此基础上,我们试着来开发一个完整的项目.这篇文章我们从用户的注册.登录着手,试着开发用户模块的相关的代码. 用户 ...

  2. 如何用Eggjs从零开始开发一个项目(3)

    上一篇中我们编写了用户注册登录.登录的代码,学习了如何进行用户的认证(JWT),如何安全地存储用的密码(hash).这一篇我们有以下2个任务: 获取token中的数据: 通过model来同步数据库. ...

  3. Cordova之如何用命令行创建一个项目(完整示例)

    原文:Cordova之如何用命令行创建一个项目(完整示例) 1. 创建cordova项目 (注意:当第一次创建或编译项目的时候,可能系统会自动下载一些东西,需要一些时间.) 在某个目录下创建cordo ...

  4. YII框架开发一个项目的通用目录结构

    YII框架开发一个项目的通用目录结构: 3 testdrive/ 4 index.php Web 应用入口脚本文件 5 assets/ 包含公开的资源文件 6 css/ 包含 CSS 文件 7 ima ...

  5. github如何多人开发一个项目

    github如何多人开发一个项目 一.总结 一句话总结:a.点项目里面的Settings->Collaborators,来添加参与者(比如github用户名), b.向他发送项目的link,让他 ...

  6. 从零开始, 开发一个 Web Office 套件 (2): 富文本编辑器

    书接前文: 从零开始, 开发一个 Web Office 套件 (1): 富文本编辑器 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Of ...

  7. 从零开始, 开发一个 Web Office 套件 (3): 鼠标事件

    这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...

  8. 从零开始, 开发一个 Web Office 套件(4):新的问题—— z-index

    <从零开始, 开发一个 Web Office 套件>系列博客目录 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office ...

  9. 《从零开始, 开发一个 Web Office 套件》系列博客目录

    这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...

随机推荐

  1. CCF计算机软件能力认证试题练习:201912-5 魔数

    CCF计算机软件能力认证试题练习:201912-5 魔数 前置知识:BFS,线段树等 \(f(x) = (x\%A)\%B\) 这个函数值的和直接用线段树维护是不太行的(也可能是我不知道),后来想了很 ...

  2. Educational Codeforces Round 41

    Educational Codeforces Round 41  D. Pair Of Lines 考虑先把凸包找出来,如果凸包上的点数大于\(4\)显然不存在解,小于等于\(2\)必然存在解 否则枚 ...

  3. 【noi 2.6_1481】Maximum sum(DP)

    题意:求不重叠的2段连续和的最大值. 状态定义f[i]为必选a[i]的最大连续和,mxu[i],mxv[i]分别为前缀和后缀的最大连续和. 注意:初始化f[]为0,而max值为-INF.要看好数据范围 ...

  4. hdu4325 Flowers

    Problem Description As is known to all, the blooming time and duration varies between different kind ...

  5. .Net Core 国际化

    创建项目什么的就不说了吧 直接进入正题吧 我这里建的是个webapi 添加资源文件 1.首先我们创建一个Language文件夹,这就是我们在后面Startup类中需要配置的目录名. 2.然后我们在La ...

  6. Python 相关

    循环使用迭代器 Python中使用for循环时,内置容器的默认循环都是有迭代器的.使用迭代器每次只会读出一小部分到内存,不断往后next. 通常建议在没有必要的情况下不使用for key,value ...

  7. JS编程练习:将目标节点内部的子节点逆序

    将目标节点内部的子节点逆序 1 <body> 2 <div> 3 <p></p> 4 <span></span> 5 <e ...

  8. 记一次 lampiao渗透(Drupal+脏牛提权)

    vulnhub|渗透测试lampiao 题记 最近在打靶机,发现了一个挺有意思的靶机,这里想跟大家分享一下. 环境准备 vulnhub最近出的一台靶机 靶机(https://www.vulnhub.c ...

  9. 在Python里,用股票案例讲描述性统计分析方法(内容来自我的书)

    描述性统计是数学统计分析里的一种方法,通过这种统计方法,能分析出数据整体状况以及数据间的关联.在这部分里,将用股票数据为样本,以matplotlib类为可视化工具,讲述描述性统计里常用指标的计算方法和 ...

  10. CDD All In One

    CDD All In One 组件驱动开发 (CDD) refs https://www.componentdriven.org/ https://www.learnstorybook.com/int ...