亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Eggjs小試

waltr / 2075人閱讀

摘要:項目都很小,但為了進(jìn)一步了解,特意選擇了作為框架基礎(chǔ)開發(fā)后端服務(wù)。能將請求限制在同源網(wǎng)站,即只有擁有專有令牌的網(wǎng)站發(fā)送請求才會正確響應(yīng)。項目生產(chǎn)靜默部署,啟動使用,停止使用。不足工具函數(shù)的訪問需要自己手動添加擴(kuò)展另沒有寫測試,希望下次補(bǔ)上。

前言

這段時間,用Eggjs作為后端服務(wù)框架開發(fā)了幾個項目。項目都很小,但為了進(jìn)一步了解Eggjs,特意選擇了Eggjs作為框架基礎(chǔ)開發(fā)后端服務(wù)。期間也遇到過一些問題和坑,還有幾個值得注意的點,下面來講一下我這段時間開發(fā)的總結(jié)。

Egg.js 為企業(yè)級框架和應(yīng)用而生 ,我們希望由 Egg.js 孕育出更多上層框架,幫助開發(fā)團(tuán)隊和開發(fā)人員降低開發(fā)和維護(hù)成本。

這個是Eggjs文檔對Eggjs的解釋,關(guān)于Eggjs的詳細(xì)介紹和使用請點解前面的地址;相對于Egg.js 1.x版本的文檔,已經(jīng)有很大的改進(jìn)了,很多關(guān)鍵的地方都可以比較完整講解和帶有代表性的實例。

步驟 開始

用的Egg.js版本是2.2.1,對環(huán)境有一定的要求,本人用的配置如下:

操作系統(tǒng):macOS

運(yùn)行環(huán)境:v9.8.0

使用腳手架快速創(chuàng)建項目:

$ npm i egg-init -g
$ egg-init egg-example --type=simple
$ cd egg-example
$ npm i

項目安裝完畢,啟動項目:

$ npm run dev
$ open localhost:7001

至此,項目順利建立及啟動完畢。

項目結(jié)構(gòu):(摘自文檔)

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

上述目錄也是一個給開發(fā)者一個目錄創(chuàng)建的指南,但按照文檔建立的項目目錄結(jié)構(gòu)沒有那么全,基本上標(biāo)注為“可選”的都是初始沒有的,在/config目錄里也只有plugin.jsconfig.default.js兩個文件,其他文件要自己根據(jù)需求創(chuàng)建。

建立控制器Controller

初始項目里會有一個示例Controller,在創(chuàng)建一個新的Controller可以參考/app/controller/home.js的示例,一般而言,推薦使用module.exports暴露出一個類或者參數(shù)為app返回一個類的函數(shù)(文檔示例中為箭頭函數(shù),其他方式?jīng)]試過不清楚),類里面包含著這塊業(yè)務(wù)的一些操作,下面在控制器文件目錄/app/controller/里新建一個文件名為user.js的控制器文件:

// 繼承egg的控制器
const Controller = require("egg").Controller;
class UserController extends Controller {
  async index() {
    const { ctx } = this;
    const { name } = ctx.request.body;
    ctx.body = `hi, ${name}`;
  }
  async getUserById() {
     const { userId } = this.ctx.request.body;
     // 使用業(yè)務(wù)函數(shù)查詢用戶信息
     const userInfo = await this.service.user.findById(userId);
     this.ctx.body = {
         msgCode: 0,
         message: "成功",
         data: userInfo
     };
  }
}
// 注意:一定要將控制器暴露出去,否則請求的時候會報找不到該controller的錯誤;
module.exports = UserController;
添加路由

路由代碼在/app目錄之下,文件名router.js,添加路由的代碼如下:

// 參數(shù)app為全局應(yīng)用的對象
module.exports = app => {
    const { router, controller, middleware } = app;
    // 在這里controller相當(dāng)于app下的controller文件目錄,user為user.js,index為控制器類的index方法
    router.get("/", controller.user.index); 
};
編寫業(yè)務(wù)

通常,controller主要處理數(shù)據(jù)的結(jié)構(gòu)和處理返回的結(jié)果,具體的涉及的業(yè)務(wù)由service業(yè)務(wù)類方法完成,編寫service,在目錄/app/service/下建立user.js文件,并編寫代碼:

// 同樣要繼承egg的Service類
const Service = require("egg").Service;
class UserService extends Service {
    // 根據(jù)用戶id查找用戶
    async findUserById(id) {
        const mysql = this.app.mysql;
        const result = await mysql.get("users", { id });
        return result;
    }
}
module.exports = UserService;
添加插件

eggjs simple 版本旨在根據(jù)業(yè)務(wù)需求添加eggjs的插件來搭建上層框架。在本人開發(fā)過程中,用到的一些插件做簡要說明。

插件安裝:

$ npm i --save egg-pluginName

在文件/config/plugin.js添加配置:

exports.pluginName = {
  enable: true,
  package: "egg-pluginName",
};

需要插件初始化配置的情況下,修改/config/config.default.js

config.pluginName = {
    // 配置項
};
egg-mysql

因使用mysql數(shù)據(jù)庫,需要一個nodejsmysql的操作庫,基于eggjs選擇了egg-mysql ,操作文檔點擊這里?;镜臄?shù)據(jù)庫增刪查改都能操作,寫起來還挺方便,但是有個需求,編寫某個接口,返回當(dāng)前用戶某一段時間的數(shù)據(jù),這就比較蛋疼了,找了很久,就連egg-mysql封裝的庫ali-rds查看了源碼也找不到這類方法,無奈之下,只能通過組織原生的mysql查詢語句去動態(tài)拼湊,雖然不推薦,不過如果找到更好的方法,還是愿意改寫的。

查詢指定日期數(shù)據(jù)的mysql相關(guān)參考資料:

http://www.jb51.net/article/1...

https://www.cnblogs.com/benef...

https://www.cnblogs.com/softi...

egg-redis
redis相當(dāng)于基于內(nèi)存的一個微型數(shù)據(jù)庫,其存取速度非??欤a執(zhí)行的時候幾乎感覺不到阻塞,這里使用egg-redis作為項目對redis的操作庫,文檔點擊這里。文檔說明解析了基本的存取和設(shè)置操作,對于較為復(fù)雜的操作只能通過查看redis的官方文檔,對應(yīng)的命令小寫即為方法名:
redis命令DECR,對應(yīng)的方法使用:
// /app/controller/user.js
const value = await this.app.redis.decr(keyName);
擴(kuò)展內(nèi)置對象

添加過幾個插件之后,發(fā)現(xiàn)其中的源代碼都是以擴(kuò)展內(nèi)置對象的方式去掛載相關(guān)的庫或者插件的。

ctx

文檔原文:“一般來說屬性的計算在同一次請求中只需要進(jìn)行一次,那么一定要實現(xiàn)緩存,否則在同一次請求中多次訪問屬性時會計算多次,這樣會降低應(yīng)用性能。

推薦的方式是使用 Symbol + Getter 的模式?!?/p>

const jwt = require("jsonwebtoken");
const JWT = Symbol("Context#jwt");
module.exports = {
  get jwt() {
    if (!this[JWT]) {
      this[JWT] = jwt;
    }
    return this[JWT];
  }
};

第一次擴(kuò)展cxt對象的時候,不明白為何要使用Symbol + Getter的模式,后來基于這個問題,查找資料,發(fā)現(xiàn)這種方式更能避免和其他屬性名發(fā)生沖突,上述代碼中,ctxjwt定義為只讀方式。在方便維護(hù)的同時,生成一個帶有命名空間(Context#jwt)字符串描述的Symbol實例數(shù)據(jù), 作為ctx的屬性,通過只讀屬性jwt來獲取內(nèi)部的JWT屬性。
PS:

ctx.JWT == ctx[JWT] // false

關(guān)于Symbol的介紹和使用請參考阮一峰的ES6。

app

在擴(kuò)展app對象的時候,遇到個問題,就是如果需要獲取ctx怎么辦?
查找文檔,找到了在擴(kuò)展app對象時,只需要在函數(shù)體里添加一句代碼:

const ctx = app.createAnonymousContext();

就可以獲取ctx對象,這對于使用其他函數(shù)提供了一道橋梁。

編寫中間件
eggjs的中間件處理流程遵循koa的洋蔥式請求模型
中間件的寫法:
module.exports = options => {
    return async function middleWareFunctionName (ctx, next) {
        // 控制器之前業(yè)務(wù)處理代碼
        // ...
        await next();
        //控制器之后業(yè)務(wù)處理代碼
        // ...
    }
}

中間件以返回一個處理業(yè)務(wù)的函數(shù)為主體,函數(shù)接收兩個參數(shù):ctxnext。ctx則是請求級別的對象,next()方法可以讓請求進(jìn)入下一個步驟。特別注意的是:在一個控制器中,有對請求到達(dá)下一步之前做一些操作的,可以控制next()在代碼流程中的位置,其后也可以處理請求之后的操作。

制定定時任務(wù)

eggjs寫定時任務(wù)也是非常簡單的,關(guān)注于業(yè)務(wù)代碼,加以簡單的配置,即可使用定時任務(wù)。
下面是一個簡單的定時統(tǒng)計業(yè)務(wù)數(shù)據(jù)的定時任務(wù):

const Subscription = require("egg").Subscription;

class Statistics extends Subscription {
  // 通過 schedule 屬性來設(shè)置定時任務(wù)的執(zhí)行間隔等配置
  static get schedule() {
    return {
      cron: "00 59 23 * * *", // 秒 分 時 日 月 年
      // interval: "10s", // 設(shè)置時間間隔觸發(fā),單位s為秒,ms為毫秒
      type: "worker", // all 指定所有的 worker 都需要執(zhí)行, worker 為某一個 worker 執(zhí)行
    };
  }

  // subscribe 是真正定時任務(wù)執(zhí)行時被運(yùn)行的函數(shù)
  async subscribe() {
   // 定時任務(wù)業(yè)務(wù)代碼
   // ...
  }
}

module.exports = Statistics;

在程序啟動的時候,就會在配置的指定時機(jī)執(zhí)行相關(guān)的業(yè)務(wù)代碼。

配置(待補(bǔ)充) csrf的討論

eggjsv2.x版本之后默認(rèn)開啟了csrf插件,已確?;?b>cookie存儲驗證信息的網(wǎng)站信息安全。

csrf能將請求限制在同源網(wǎng)站,即只有擁有“專有令牌”的網(wǎng)站發(fā)送請求才會正確響應(yīng)。此處容易與jwt的作用混淆,可以看看這篇文章。

跨域
使用egg-cors;
前后端分離用戶驗證
使用jwt驗證

jwt則在認(rèn)證方式上跟csrf上有所不同,jwt可以在不使用cookie的情況下,以token的方式在前后端交互數(shù)據(jù)的body里傳輸,也可以在header里設(shè)置相關(guān)信息,詳細(xì)可以參考這篇文章。

日志(待補(bǔ)充)
類的寫法
遠(yuǎn)程機(jī)開發(fā)部署
文檔中,有《應(yīng)用部署》一文,里面介紹的很詳細(xì)的。使用egg-script插件啟動生產(chǎn)環(huán)境中的應(yīng)用程序。項目生產(chǎn)靜默部署,啟動使用npm start,停止使用npm stop另,在開發(fā)環(huán)境里想要使用pm2管理進(jìn)程后臺啟動,--watch會不斷打印控制臺日志,原因不清楚。
生產(chǎn)環(huán)境部署

啟動命令:

$ npm install --production
$ npm start

停止命令:

$ npm stop
總結(jié) 優(yōu)點
使用eggjs開發(fā)企業(yè)級應(yīng)用還是相當(dāng)方便的,雖然說要根據(jù)需求裝,但安裝和配置步驟非常簡單,很多有用的業(yè)務(wù)配置都能夠很方便快速配置好,還可以區(qū)分環(huán)境,項目結(jié)構(gòu)和調(diào)用方式很合理。
不足
工具函數(shù)的訪問需要自己手動添加擴(kuò)展
沒有寫測試,希望下次補(bǔ)上。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/95471.html

相關(guān)文章

  • Eggjs下Restful API的實現(xiàn)

    摘要:今天就簡要說說下的實現(xiàn)。主要的原因是的文檔寫的不太清楚,方便新人快速上手。導(dǎo)致我們一目十行去掃文檔的時候,有時總會覺得有些莫名,的實現(xiàn)就是其中之一。其實這和我本身對的了解不深入有關(guān),但是也沒有文檔和我說實現(xiàn)啊。 這兩天真的是宅的骨頭都發(fā)霉了,春困秋乏夏打盹,也是醉了。今天就簡要說說eggjs下Restful API的實現(xiàn)。主要的原因是egg的文檔寫的不太清楚,方便新人快速上手。話說eg...

    linkin 評論0 收藏0
  • 造輪子 - EGGJS的MySQL操作庫

    摘要:最近學(xué)習(xí),學(xué)習(xí)過程中使用官方推薦的庫,感覺官方庫不太好用,基礎(chǔ)的沒問題。介紹這個輪子其實是很早以前就造好的,主要參考的數(shù)據(jù)庫操作方式。將設(shè)置表名設(shè)置查詢字段聯(lián)表等操作進(jìn)行鏈?zhǔn)讲僮鳎o人一種語義化操作數(shù)據(jù)庫的感覺。 最近學(xué)習(xí)eggjs,學(xué)習(xí)過程中使用官方推薦的MySQL庫,感覺官方庫不太好用,基礎(chǔ)的CURD沒問題。但是復(fù)雜點的操作就不行了,雖然官方還有一個egg-sequelize,但是...

    Alex 評論0 收藏0
  • 記一次eggjs+axios傳輸multipart的糾錯過程

    摘要:總所周知,的策略讓每次都要發(fā)送碼驗證,為了方便,我在的里作了前置攔截。結(jié)果不幸從此發(fā)生最開始沒有看官方文檔,以為應(yīng)該加在里面,又沒有考慮到要上傳格式的文檔,所以直接結(jié)果發(fā)送的是。這很正常,閱讀源碼知為時會自動添加的頭。不加又以上傳了。 總所周知,egg的csrf策略讓post每次都要發(fā)送token碼驗證,為了方便,我在axios的interceptor里作了前置攔截。 結(jié)果不幸從此發(fā)生...

    CarterLi 評論0 收藏0
  • eggjs】部署egg時碰到的日志權(quán)限問題

    摘要:前兩天將一個部署到服務(wù)器時,用就是啟動不了,錯誤信息為無權(quán)限創(chuàng)建目錄。查看工作目錄權(quán)限,當(dāng)前用戶是有權(quán)限的,看了源碼,原來是用的包的問題。首先,在生產(chǎn)環(huán)境下的啟動是通過啟動的。 前兩天將一個egg部署到服務(wù)器時,用npm start就是啟動不了,錯誤信息為無權(quán)限創(chuàng)建log目錄。查看工作目錄權(quán)限,當(dāng)前用戶是有權(quán)限的,看了源碼,原來是用的npm包的問題。這里簡單記錄下解決過程。 首先,在生...

    waterc 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<