前言
? ? ? ? Eggjs 是阿里巴巴團隊開發(fā)的,一個基于 Koajs 的框架,相當于二次封裝,和 Koajs 一樣,它的性能也是比較高的,但是相比較 Koajs ,并沒有那么高的自由度,相比于 Koajs 來說,Eggjs 這種帶有規(guī)范性的開發(fā)更適合在企業(yè)中使用。
? ? ? ? Swagger 是RESTFUL接口的文檔在線自動生成工具。
? ? ? ? Sequelize 是基于Nodejs功能強大的異步ORM框架。 同時支持PostgreSQL, MySQL, SQLite and MSSQL多種數據庫
項目搭建
? ? ? ? Eggjs 分為兩種搭建方式,快速搭建和逐步搭建,為了讓大家更好的了解 Egg.js,這里使用逐步搭建。
項目目錄
egg_folder
├── app
│ ├── contract
│ │ └── format.js
│ ├── controller
│ │ └── home.js
│ ├── extend
│ │ └── helper.js
│ ├── service
│ │ └── home.js
│ └── router.js
├── config
│ └── config.default.js
│ └── plugin.js
├── node_modules
└── package.json
初始化項目
? ? ? ? 在項目文件夾( egg_folder )里首先 cmd 運行npm init來獲取package.json文件,再運行npm install egg --save和npm install egg-bin --save-dev安裝 Eggjs 依賴包和 本地開發(fā)工具( 沒安裝 npm 的自行安裝 )。
? ? ? ? 之后在package.json的 script 里面配置運行dev命令
/* egg_folder/package.json */
"scripts": {
"dev": "egg-bin dev --port 7007",
"dbinit": "egg-sequelize-auto -o ./app/model -h localhost -p 3306 -d library -u root -x haosql",
"test": "echo \"Error: no test specified\" && exit 1"
},
? ? ? ? 然后在 cmd 運行npm run dev,如果順利就會如下圖所示。
? ? ? ? 如果直接在瀏覽器打開,就會出現這樣的界面,500 那是因為什么都沒做,但至少項目已經成功的啟動了。
配置 Cookie 秘鑰
? ? ? ? 首先配置 Cookie 秘鑰,詳見官網。
/* egg_folder/config/config.default.js */
'use strict';
exports.keys = 'egg_folder';
keys 配置成一個字符串,可以按照逗號分隔配置多個 key
配置路由
? ? ? ? 接下來開始配置路由,在 router.js 里開始定義路由:
/* egg_folder/app/router.js */
'use strict';
module.exports = function (app) {
app.router.get('/', 'home.index'); // 第一個參數為 url 路徑,第二個參數的說直接點就是 controller 下的"文件名.方法"( 例如:'home.index'就會去找 egg_folder/app/controller 下的 home.js,然后再這個 js 里面找到 index 方法 )。
}
? ? ? ? 其中 app 是 Eggjs 的全局應用對象,具體詳見官網
Application 是全局應用對象,在一個應用中,只會實例化一個,它繼承自 Koa.Application,在它上面我們可以掛載一些全局的方法和對象。我們可以輕松的在插件或者應用中擴展 Application 對象。
定義 Controller
? ? ? ? 設置完后就在 home.js 里面定義 index 方法:
/* egg_folder/app/controller/home.js */
'use strict';
const Controller = require('egg').Controller;
// 通過定義 Controller 類的方式來編寫代碼,所有的 Controller 文件都必須放在 app/controller 目錄下。
class HomeController extends Controller {
async index () {
this.ctx.body = 'Hello World!'; // 設置響應內容。
}
}
module.exports = HomeController;
? ? ? ? 重新運行 npm run dev ,頁面就不會報錯了。
安裝和配置 Swagger 和 Sequelize
? ? ? ? 現在已經完成頁面的顯示了,接下來就可以搭配 Swagger 和Sequelize 開始寫接口了。
? ? ? ? 首先還是安裝依賴包。
npm install egg-sequelize --save
npm install egg-sequelize-auto --save-dev // 對照數據庫自動生成相應的 models 減少了對數據庫進行增刪改查時的 sql 語句的編寫。
npm install egg-swagger-doc --save
? ? ? ? 因為是插件,所以要在 config.default.js 和 plugin.js 里配置插件信息。
/* egg_folder/config/config.default.js */
'use strict';
exports.keys = "egg_folder";
// egg-swagger-doc 配置信息。
exports.swaggerdoc = {
dirScanner: './app/controller', // 配置自動掃描的控制器路徑。
// 接口文檔的標題,描述或其它。
apiInfo: {
title: 'NAPI', // 接口文檔的標題。
description: 'swagger-ui for NAPI document.', // 接口文檔描述。
version: '1.0.0', // 接口文檔版本。
},
schemes: ['http', 'https'], // 配置支持的協議。
consumes: ['application/json'], // 指定處理請求的提交內容類型(Content-Type),例如application/json, text/html。
produces: ['application/json'], // 指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回。
securityDefinitions: { // 配置接口安全授權方式。
// apikey: {
// type: 'apiKey',
// name: 'clientkey',
// in: 'header',
// },
// oauth2: {
// type: 'oauth2',
// tokenUrl: 'http://petstore.swagger.io/oauth/dialog',
// flow: 'password',
// scopes: {
// 'write:access_token': 'write access_token',
// 'read:access_token': 'read access_token',
// },
// },
},
enableSecurity: false, // 是否啟用授權,默認 false(不啟用)。
// enableValidate: true, // 是否啟用參數校驗,默認 true(啟用)。
routerMap: true, // 是否啟用自動生成路由,默認 true (啟用)。
enable: true, // 默認 true (啟用)。
};
// 數據庫配置信息。
exports.sequelize = {
dialect: 'mysql', // 數據庫類型,支持 mysql,sqlite,mssql,pgsql,oracle。
host: "localhost", // 數據庫服務器地址。
port: 3344, // 數據庫連接端口號。
database: "database", // 數據庫名稱。
username: "username", // 數據庫登錄用戶名。
password: "password", // 數據庫登錄密碼。
define: {
freezeTableName: true, // Model 對應的表名將與model名相同。
timestamps: false // 默認情況下,Sequelize會將createdAt和updatedAt的屬性添加到模型中,以便您可以知道數據庫條目何時進入數據庫以及何時被更新( 確實是太方便了,然而我們一般用不到 ....)。
}
};
/* egg_folder/config/plugin.js */
'use strict';
// 配置 egg-swagger-doc 插件信息。
exports.swaggerdoc = {
enable: true, // 是否啟用。
package: 'egg-swagger-doc', // 指定包名稱。
};
// 配置 egg-sequelize 插件信息。
exports.sequelize = {
enable: true, // 是否啟用。
package: 'egg-sequelize', // 指定包名稱。
};
? ? ? ? 之后在 package.json 的 script 里面添加把數據庫生成 models 的命令( -o 表示生成 models 的路徑,-h 表示主機,-p 表示端口,-d 表示數據庫, -u 表示用戶名,-x 表示密碼。別問為什么這么命名.... )。
"scripts": {
"dev": "egg-bin dev --port 7007",
"dbload": "egg-sequelize-auto -o ./app/model -h localhost -p 3344 -d database -u username -x password",
"test": "echo \"Error: no test specified\" && exit 1"
},
? ? ? ? 然后直接運行 npm run dbload ,就會生成相對應的 model 了( 如果配置都沒錯的話.... )。
編寫 Service 和 Controller
? ? ? ? 配置完畢,就可以開始寫 Service( 業(yè)務層 ) 了。
/* egg_folder/app/service/book.js */
'use strict';
const Service = require('egg').Service;
// 通過定義 Service 類的方式來編寫代碼,所有的 Service 文件都必須放在 app/service 目錄下。
class BookService extends Service {
constructor(ctx) {
super(ctx); // 調用父對象上的函數。
this.tableName = 'Book'; // 數據庫表名。
this.database = this.ctx.model[this.tableName]; // 獲取 model 下的表( model 相當于數據庫的表 )。
}
/**
* 根據Id獲取表信息。
* @param {*} id
*/
async selectById (id) {
const result = await this.database.findByPk(id); // sequelize 內置查詢方法。
return result;
}
}
module.exports = BookService;
? ? ? ? 然后開始寫 Controller ( 控制器 )調用 Service( 業(yè)務層 ) 進行業(yè)務處理。
/* egg_folder/app/controller/book.js */
'use strict';
const Controller = require('egg').Controller;
/**
* @controller BookController( 注釋必寫,swagger-doc是根據這段注釋來生成接口的 )。
*/
class BookController extends Controller {
/** ( 注釋必寫,swagger-doc是根據這段注釋來生成接口詳細信息的 )。
* @summary 根據ID查詢信息。
* @description 根據ID查詢信息。
* @router get /version01/controllers/selectById ( get 表示設置請求為 get 請求,最后的 selectById 對應下面的 selectById 方法 )。
* @request query integer Id 需要去查新的ID。( get 對應 query 請求,請求值設定為 integer 純數字類型,ID 為請求的字段,注意大小寫,和下面的方法要一一對應,不然會報錯 )。
* @response 200 JsonBody 返回結果。( 對應 contract 里面的驗證屬性,下面會提到 。)
*/
async selectById () {
const ctx = this.ctx; // 當前請求的上下文 Context 對象的實例,通過它我們可以拿到框架封裝好的處理當前請求的各種便捷屬性和方法。
const service = this.service; // 應用定義的 Service,通過它我們可以訪問到其他業(yè)務層,等價于 this.ctx.service 。
const param = ctx.query; // 獲取請求參數。
const result = await service.book.selectById(param.Id); // 查找 service/book.js 下的 selectById 方法。
this.JsonBody(result);
}
/*
* 對返回的數據結果進行封裝。
*/
JsonBody (data) {
this.ctx.body = {
result: data,
};
}
}
module.exports = BookController;
上面 Controller 的注釋必須要按照規(guī)范填寫,不然 swagger-doc 會無法生成對應的結果,甚至報錯。具體格式可以去 swagger-doc 的官網或 github 查看。
編寫 Contract
? ? ? ? Contract 相當于驗證,在接收請求和返回數據的時候對數據進行格式約束。
/* egg_folder/app/contract/format.js */
module.exports = {
JsonBody: { // 這個名字對應上面 Controller 注釋的@response 的 JsonBody。
result: { type: 'string' }, // 服務器返回的數據。
},
};
? ? ? ? 最后,cmd 運行 npm run dev,然后再瀏覽器上輸入 URL( 由于用了 swagger-doc,所以要在后面加上 /swagger-ui.html 來訪問 swagger-ui,嫌麻煩的也可以自己改 )。
至此 大功告成,利用這些已經可以完成對數據的增刪查改了,這是我寫的一個小 DEMO,已經成功完成增刪查改。
總結步驟:
- 初始化項目;
- 建立項目目錄;
- 配置 Cookie 秘鑰;
- 配置路由;
- 安裝和配置 Swagger 和 Sequelize;
- 根據數據庫生成對應的 Model;
- 編寫 Service( 業(yè)務層 ) 和 Controller( 控制器 );
- 編寫 Contract 對格式進行約束;
- 最后
npm run dev運行項目,結束