前言

“纸上得来终觉浅,绝知此事要躬行。”虽然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. 为何 JVM TLAB 在线程退还给堆的时候需要填充 dummy object

    TLAB 全网最硬核的解析,请参考:全网最硬核 JVM TLAB 分析 TLAB 在何时退还给堆? 有两种情况: 当前 TLAB 不足分配,并且剩余空间小于当前线程最大浪费空间限制时. 发生 GC 时 ...

  2. Codeforces Global Round 7 D2. Prefix-Suffix Palindrome (Hard version)(Manacher算法)

    题意: 取一字符串不相交的前缀和后缀(可为空)构成最长回文串. 思路: 先从两边取对称的前后缀,之后再取余下字符串较长的回文前缀或后缀. #include <bits/stdc++.h> ...

  3. 【noi 2.6_3531】判断整除(DP)

    题意:给一个正整数数列,可将其相加或相减,问是否有一个结果能被K整除. 解法:似上一题"糖果"的状态定义,f[i][j]表示是否有一个选了前 i 个数的结果模K余j. P.S. 可 ...

  4. KMP && Manacher && 扩展KMP整理

    KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...

  5. zjnu1181 石子合并【基础算法・动态规划】——高级

    Description 在操场上沿一直线排列着  n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆,  并将新的一堆石子数记为该次合并的得分.允许在第一次合并前对调一 ...

  6. 二进制安装kubernetes(一) 环境准备及etcd组件安装及etcd管理软件etcdkeeper安装

    实验环境: 架构图: 主机环境: 操作系统:因docker对内核需要,本次部署操作系统全部采用centos7.6(需要内核3.8以上) VM :2C 2G 50G * 5  PS:因后面实验需要向k8 ...

  7. Java RMI 实现一个简单的GFS(谷歌文件系统)——介绍篇

    本系列主要是使用Java RMI实现一个简单的GFS(谷歌文件系统,google file system),首先整体简单介绍下该项目. [为了更好的阅读以及查看其他篇章,请查看原文:https://w ...

  8. 力扣119.杨辉三角II-C语言实现

    题目 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例: 输入: 3 输出: [1,3,3,1] 来源:力扣(LeetCod ...

  9. 网络安全知识--PHP代码审计/Web For Pantesters 的 SQL injection

    SQL 注入一般流程 判断有无注入 单引号判断: ?name=root' 对应语句 select * from table where name='root'' 不符合语法规范,报错,说明有注入 an ...

  10. Unknown command '\b'. 关于Mysql导入外部数据库脚本报错的解决

    来自网络转载 还是字符集的问题 使用source导入外部sql文件: mysql> source F:\php\bookorama.sql;--------------source F:---- ...