eggJS 入門分享

快速初始化

我們推薦直接使用腳手架,只需幾條簡單指令,即可快速生成項目:


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

啓動項目:


$ npm run dev
$ open localhost:7001

啓動後的界面

image.png

注意:這裏默認地址是7001,如果修改,可以在config配置文件裏面做如下修改:

// 自定義端口
config.cluster = {
  listen: {
  	port: 7010
  }
};

框架目錄結構

  • egg.js是約定優於配置的
egg-project
├── package.json
├── app.js (可選)
├── agent.js (可選)
├── app
|   ├── router.js
│   ├── controller
│   |   └── home.js
│   ├── service (可選)
│   |   └── user.js
│   ├── middleware (可選)
│   |   └── response_time.js
│   ├── schedule (可選)
│   |   └── my_task.js
│   ├── public (可選)
│   |   └── reset.css
│   ├── view (可選)
│   |   └── home.tpl
│   └── extend (可選)
│       ├── helper.js (可選)
│       ├── request.js (可選)
│       ├── response.js (可選)
│       ├── context.js (可選)
│       ├── application.js (可選)
│       └── agent.js (可選)
├── config
|   ├── plugin.js
|   ├── config.default.js
│   ├── config.prod.js
|   ├── config.test.js (可選)
|   ├── config.local.js (可選)
|   └── config.unittest.js (可選)
└── test
    ├── middleware
    |   └── response_time.test.js
    └── controller
        └── home.test.js

如上,由框架約定的目錄:

  • app/router.js 用於配置 URL 路由規則,具體參見 Router
  • app/controller/** 用於解析用戶的輸入,處理後返回相應的結果,具體參見 Controller
  • app/service/** 用於編寫業務邏輯層,可選,建議使用,具體參見 Service
  • app/middleware/** 用於編寫中間件,可選,具體參見 Middleware
  • app/public/** 用於放置靜態資源,可選,具體參見內置插件 egg-static
  • app/extend/** 用於框架的擴展,可選,具體參見框架擴展
  • config/config.{env}.js 用於編寫配置文件,具體參見配置
  • config/plugin.js 用於配置需要加載的插件,具體參見插件
  • test/** 用於單元測試,具體參見單元測試
  • app.jsagent.js 用於自定義啓動時的初始化工作,可選,具體參見啓動自定義。關於agent.js的作用參見Agent機制

由內置插件約定的目錄:

  • app/public/** 用於放置靜態資源,可選,具體參見內置插件 egg-static
  • app/schedule/** 用於定時任務,可選,具體參見定時任務

怎麼寫一個接口?

後臺接口避免不了和數據庫打交道,下面例子咱們使用MySQL,ORM使用sequelize
首先安裝MySQL數據庫(安裝教程),以及navicat界面管理工具,這樣就可以驗證自己操作數據庫是否成功。

egg中使用MySQL

安裝對應的插件 egg-mysql


$ npm i --save egg-mysql

開啓插件:


// config/plugin.js
exports.mysql = {
enable: true,
package: ‘egg-mysql’,
};

config/config.${env}.js 配置各個環境的數據庫連接信息。更詳細教程參考官方文檔


安裝並配置 egg-sequelize 插件

(它會輔助我們將定義好的 Model 對象加載到 app 和 ctx 上)和 mysql2 模塊

  • 安裝


npm install --save egg-sequelize mysql2

  • config/plugin.js 中引入 egg-sequelize 插件


exports.sequelize = {
enable: true,
package: ‘egg-sequelize’,
};

這裏有個坑,egg項目初始化plugin.js導出使用的module.exports,而教程裏又是 exports導出,這兩者不能並存的,有多坑?你自己體驗吧!如果使用module.exports就要以key: value的形式配置插件!不懂這倆區別的人就容易入坑!!!嗯~我就入了,所以推薦一篇文章https://www.imooc.com/article/34483

image.png

  • config/config.default.js 中編寫 sequelize 配置
​
config.sequelize = {

    dialect: 'mysql',

    host: '127.0.0.1',

    port: 3306,

    database: 'dev2',

    username: 'root',

    password: '',

    timezone: "+08:00",

};

​

更詳細教程參考官方文檔


1. Router

Router 主要用來描述請求 URL 和具體承擔執行動作的 Controller 的對應關係, 框架約定了 app/router.js 文件用於統一所有路由規則。通過統一的配置,我們可以避免路由規則邏輯散落在多個地方,從而出現未知的衝突,集中在一起我們可以更方便的來查看全局的路由規則。

下面我們添加一個註冊接口,在app/router.js添加

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;

  //註冊
  app.post("/example/register", app.controller.userControl.register);	

  router.get('/*', controller.home.index);
};

更詳細教程參考官方文檔


2. Controller

一切準備就緒後,開始我們的第一個Controller。我們下載的simple類型的example目錄結構中是有controller這樣一個目錄。注意我在文章開頭提到過,egg.js是約定優於配置的,這些目錄是什麼意思都可以在(官方教程的目錄結構中看到)這個controller目錄結構就是指明這個目錄就是一個Controller,所有跟Controller有關的東西都放在這個目錄下面。

下面我們自定義一個controller看看效果,在controller文件夾下新建一個userControl.js文件

'use strict';

const Controller = require('egg').Controller;
class userControl extends Controller {
    async register() {
        const { ctx } = this;
        const params = ctx.request.body;  // 獲取請求參數

        // 校驗規則
        const rule = {
            username: { type: 'string' },
            password: { type: 'string' },
        };

        try {
            ctx.validate(rule, params);  // 參數校驗

            const data = await ctx.service.userServer.register(params);  // 把業務邏輯交給service處理

            ctx.body = JSON.stringify(data);  // 成功返回前端
        } catch (err) {
            ctx.body = JSON.stringify(err);  // 異常返回前端
            ctx.logger.info("userControl.register-error: ", JSON.stringify(err));  // 異常打印日誌
        }
    }
}

module.exports = userControl;

參數校驗egg自帶了egg-validate,用的不是很舒服,我個人推薦使用egg-joi,使用方式我的博客有寫哦,
一波小廣告=>eggJS egg-joi優雅的參數校驗

更詳細教程參考官方文檔


3. Service

Service是業務邏輯層在我們自己下載的example中是沒有這麼一項的,但是在官方教程的目錄結構中是有的,只是被標註了可選。首先我們需要在app下創建一個service的文件夾用來存放service文件(注意約定大於配置),再在service文件夾下新建一個userServer.js文件用來編寫service代碼

下面我們自定義一個service看看效果,先建一個service文件夾,在service文件夾下新建一個userServer.js文件

const Service = require('egg').Service;

class userServer extends Service {

    async register(params) {
        const ctx = this.ctx;
        try {
            // 我這裏沒有做複雜的業務邏輯,註冊直接存庫,所以就調用下model裏的insertUserInfo方法
            const results = await ctx.model.UserModel.insertUserInfo(params);
            return results;
        } catch (err) {
            ctx.body = JSON.stringify(err);
        }
    }

}

module.exports = userServer;

更詳細教程參考官方文檔


4. Model

egg-sequelize會自動將sequelize實例掛載到app.model上面,然後靜態方法和屬性則會直接被綁定到app上,通過app.Sequelize進行獲取。
model層作爲MVC的最底層,需要注意到數據模型的pure,model文件也應該是純淨的,這個文件裏面應該是和數據庫中的表一一對應,一個model文件對應一個DB中的表,這個文件中不應該包含任何和邏輯相關的代碼,應該完全是數據模型的定義。

下面我們自定義一個model看看效果,先建一個model文件夾,再在model文件夾下新建一個UserModel.js文件

'use strict';

module.exports = app => {
    const Sequelize = app.Sequelize;

    const UserModel = app.model.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true,
        },
        username: {
            type: Sequelize.STRING,
        },
        password: {
            type: Sequelize.STRING,
        },
    }, {
            tableName: 'user',
            timestamps: true,
            underscoredAll: true
        });
	/**
	 * 插入數據
	 */
    UserModel.insertUserInfo = (params) => {
        return new Promise((resolve, reject) => {
            UserModel.create({
                username: params.username,
                password: params.password,
            }).then(results => {
                // console.log("UserModel.updateUserInfo-results===", results);
                if (results && results.dataValues) {
                    resolve(results.dataValues);
                } else {
                    reject(false);
                }
            }).catch((err) => {
                console.log('UserModel.updateUserInfo-err===', err);
                reject(err);
            });
        });
    };

    return UserModel;
};

sequelize使用原始查詢方法寫SQL語句使用Sequlize提供的工具函數sequelize.query來實現。
上面的插入方法用SQL寫如下:

UserModel.insertUserInfo = (params) => {
		return new Promise((resolve, reject) => {
			let sql = `INSERT INTO user (username, password,created_at, updated_at) VALUES ('${params.username}', '${params.password}', now(), now())`;

			app.model.query(sql).spread((results, metadata) => {
				// console.log("UserModel.updateUserInfo-results===", results);
                if (results && results.dataValues) {
                    resolve(results.dataValues);
                } else {
                    reject(false);
                }
			}).catch(err => {
				console.log('UserModel.insertUserInfo-err======', err);
				reject(err);
			});
		});
	};

sequelize的確很便捷,提供的方法也比較多,我這裏就拿一個舉例,其他的大家可以去網上找文章,很多的。
如果要使用連接MongoDB的話可以參考我的一篇博客eggJS 連接和使用Mongodb


咱們調用一下,看下接口返回的結果,這裏推薦一個工具postman
image.png


應用部署

  1. 在該文件下打包,生成tgz文件:tar -zcvf …/FileName.tgz

  2. 環境部署(建議下載Xshell客戶端,當然別的工具都可以,根據個人喜好~~~)

    a.進入要部署的服務器對應文件夾下,cd 等等;
    b.//創建文件 mkdir 文件名稱;
    c.打開壓縮包: rz -be;
    d.解包:tar zxvf FileName.tar;
    e.移除壓縮包: rm -rf FileName.tar

  3. 然後就可以啓動啦:npm start即可。

更詳細教程參考官方文檔


本節demo:https://gitee.com/netbuggang/egg-example

參考文獻:
https://eggjs.org/zh-cn/tutorials/index.html
https://www.jianshu.com/p/6b04330ee4a1
https://blog.csdn.net/qq_35954591/article/details/78803859

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章