Egg框架搭建后台服务【1】

94 阅读2分钟

需求

博客系统升级,本来是用 express 写的,最近发现 Egg 不错,正好学习升级一下。边学边写。

Ps:相同的功能,迭代的写法,由浅入深,做个记录。

开发

初始化

安装

node版本需要 >=14.20.0, LTS版本最低要求 8.x,npm版本 >=6.1.0

mkdir egg-blogs && cd egg-blogs
npm init egg --type=simple
npm install
npm run dev

默认启动的是 7001 端口。

创建目录结构

egg-blogs
├── package.json
├── app
|   ├── router.js
│   ├── controller
│   |   └── home.js
│   ├── service
│   |   └── user.js
│   ├── middleware
│   └── extend
│       ├── helper.js
├── config
|   ├── plugin.js
|   ├── config.default.js

安装&配置插件

npm i --save egg-mysql

在 config/plugin.js 中配置

/** @type Egg.EggPlugin */
module.exports = {
  // had enabled by egg
  // static: {
  //   enable: true,
  // }

    mysql: {
        enable: true,
        package: 'egg-mysql'
    }
};

在 config/config.default.js 中配置数据库信息

/* eslint valid-jsdoc: "off" */

/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
    /**
     * built-in config
     * @type {Egg.EggAppConfig}
     **/
    const config = exports = {};

    // use for cookie sign key, should change to your own and keep security
    config.keys = appInfo.name + '123';

    // add your middleware config here
    config.middleware = [];

    // 关闭安全配置
    config.security = {
        xframe: {
            enable: false,
        },
        csrf: {
            enable: false,
        }
    };

    // 添加mysql配置
    config.mysql = {
        client: {
            host: '127.0.0.1',
            port: 3306,
            user: 'root',
            password: '12345678',
            database: 'blogs',
            charset: 'utf8'
        },
        app: true,
        agent: false,
    };

    // add your user config here
    const userConfig = {
        // myAppName: 'egg',
    };

    return {
        ...config,
        ...userConfig,
    };
};

开发逻辑

Controller

创建 app/controller/tags.js

const {Controller} = require('egg');

class TagsController extends Controller {
    /** 获取标签列表 */
    async getTagList() {
        await this.ctx.service.tags.getTagList(this.ctx.request.query);
    }

    /** 新建标签 */
    async createTag() {
        await this.ctx.service.tags.createTag(this.ctx.request.body);
    }

    /** 更新标签 */
    async updateTag() {
        await this.ctx.service.tags.updateTag(this.ctx.request.body);
    }

    /** 删除标签 */
    async deleteTag() {
        await this.ctx.service.tags.deleteTag(this.ctx.request.query);
    }
}

module.exports = TagsController;

Service

创建 app/service/tags.js

const {Service} = require('egg');

class TagsService extends Service {
    async getTagList(params) {
        const {ctx, app} = this;
        const tagName = params?.tagName || '';
        const result = await app.mysql.query('SELECT * FROM tag WHERE tagName LIKE "%' + tagName + '%" ORDER BY create_time DESC')
        // 判断是否成功
        const isSuccess = result && Array.isArray(result);
        if (isSuccess) {
            ctx.state = 200;
            ctx.body = {
                code: 200,
                success: true,
                data: result,
                msg: '获取标签数据成功',
                show: false
            }
        } else {
            ctx.state = 200;
            ctx.body = {
                code: 500,
                success: false,
                msg: '获取标签数据失败',
                show: true
            }
        }
    }

    async createTag(params) {
        const {ctx, app} = this;
        const tagInfo = {
            id: ctx.helper.snowflakeId(),
            tagName: params.tagName,
            tagColor: params.tagColor,
            remark: params.remark,
            create_time: app.mysql.literals.now,
            update_time: app.mysql.literals.now
        }
        const result = await app.mysql.insert('tag', tagInfo);
        if (result.affectedRows === 1) {
            ctx.status = 200;
            ctx.body = {
                code: 200,
                success: true,
                data: tagInfo,
                msg: '创建标签成功',
                show: true
            }
        } else {
            ctx.status = 200;
            ctx.body = {
                code: 500,
                success: false,
                msg: '创建标签失败',
                show: true
            }
        }
    }

    async updateTag(params) {
        const {ctx, app} = this;
        const tagInfo = {
            id: params.id,
            tagName: params.tagName,
            tagColor: params.tagColor,
            remark: params.remark,
            update_time: app.mysql.literals.now
        }
        const result = await app.mysql.update('tag', tagInfo);
        const isSuccess = result && result.affectedRows === 1;
        if (isSuccess) {
            ctx.status = 200;
            ctx.body = {
                code: 200,
                success: true,
                data: tagInfo,
                msg: '修改标签成功',
                show: true
            }
        } else {
            ctx.status = 200;
            ctx.body = {
                code: 500,
                success: false,
                msg: '修改标签失败',
                show: true
            }
        }
    }

    async deleteTag(params) {
        const {ctx, app} = this;
        const ids = params.ids.split(',');
        const result = await app.mysql.beginDoomedTransactionScope(async (conn) => {
            for (let i = 0; i < ids.length; i++) {
                await app.mysql.delete('tag', {id: ids[i]});
            }
            return {success: true}
        }, ctx);
        if (result.success) {
            ctx.status = 200;
            ctx.body = {
                code: 200,
                success: true,
                msg: '删除标签成功',
                show: true
            }
        } else {
            ctx.status = 200;
            ctx.body = {
                code: 500,
                success: false,
                msg: '删除标签失败',
                show: true
            }
        }
    }
}

module.exports = TagsService;

暴露路由

在 app/router.js 中暴露路由接口

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
    const {router, controller} = app;
    router.get('/', controller.home.index);

    // 操作标签
    router.get('/tags/getTagList', controller.tags.getTagList);
    router.post('/tags/createTag', controller.tags.createTag);
    router.put('/tags/updateTag', controller.tags.updateTag);
    router.delete('/tags/deleteTag', controller.tags.deleteTag);
};

总结

基础增删改查完成,但是当前状态最好不要部署在服务器上。

问题:

  1. 安全防护并未打开
  2. SQL防注入语法不对
  3. 直接操作数据库不规范、不标准
  4. 各类安全措施没有增加
  5. 各类数据校验没有增加