首頁>技術>

1. 框架約定目錄規則

1.1 app/router.js:用於配置URL路由規則;

1.2 app/controller/** :用於解析使用者的輸入,處理後返回相應的結果;

1.3 app/service/**: 用於編寫業務邏輯層;

1.4 app/public/**: 用於放置靜態資源;

1.5 config/config.{env}.js: 用於編寫配置檔案;

1.6 config/plugin.js 用於配置需要載入的外掛;

2.內建物件

1. Application:全域性應用物件,在一個應用中,只會例項化一個物件;

在繼承於 Controller, Service 基類的例項中,可以通過 this.app 訪問到 Application 物件。

2. Request & Response:可以在 Context 的例項上獲取到當前請求的 Request(ctx.request) 和 Response(ctx.response) 例項;

3. Controller:推薦所有的 Controller 都繼承於該基類實現。該基類屬性有:

ctx - 當前請求的 Context 例項。

app - 應用的 Application 例項。

service - 應用所有的 service。

4. Service:推薦所有的Service都繼承該基類。

Service基類屬性和 Controller 基類屬性一致。

3.路由Router

路由是描述請求URL和具體承擔執行動作的Controller的對應。說的直白點,就是使用者訪問不同的路徑時應該有不同的Controller去響應不同的內容。

4.控制器Controller

1. 控制器的定義以及和路由的關聯

Controller負責解析使用者的輸入,處理後返回響應的結果。所有的Controller 檔案都必須放在 app/controller目錄下,支援多級目錄,訪問時可以通過目錄名級聯訪問。如將Controller程式碼放到 app/controller/sub/post.js 中,則可以在 router 中這樣使用:

// app/router.jsmodule.exports = app => { app.router.post('createPost', '/api/posts', app.controller.sub.post.create);}

同時,我們也可以自定義基類給控制器繼承,官方案例如下:

// app/core/base_controller.jsconst { Controller } = require('egg');class BaseController extends Controller { get user() { return this.ctx.session.user; } success(data) { this.ctx.body = { success: true, data, }; } notFound(msg) { msg = msg || 'not found'; this.ctx.throw(404, msg); }}module.exports = BaseController;

定義控制器繼承他:

//app/controller/post.jsconst Controller = require('../core/base_controller');class PostController extends Controller { async list() { const posts = await this.service.listByUser(this.user); this.success(posts); }}

5.獲取提交的資料

接收GET請求的資料:ctx.request.query 和 ctx.query.id;

接收POST請求的資料:ctx.request.body,而不是 ctx.body;post請求時,會有安全驗證問題,簡單的處理方式是關閉安全驗證:

// config/config.default.js

// 配置安全驗證

config.security = {

csrf: {

enable: false,

ignoreJSON: true,

}

}

Post資料預設大小是100kb,如需調整可在 config/config.default.js 中覆蓋框架的預設值:

 module.exports = {                  bodyParser: {                          jsonLimit: '1mb',                          formLimit: '1mb',                  },};

接收路由引數:

// app.get('/projects/:projectId/app/:appId', 'app.listApp');// GET /projects/1/app/2class AppController extends Controller {  async listApp() {    assert.equal(this.ctx.params.projectId, '1');    assert.equal(this.ctx.params.appId, '2');  }}

6.獲取上傳的檔案

記住了,你要先在 config 檔案中啟用 file 模式:

// config/config.default.jsexports.multipart = { mode: 'file',};

然後,你就可以參考下面的程式碼了:

<form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="avatar" id="avatar" multiple> <input type="file" name="avatar1" id="avatar"> <input type="file" name="avatar2" id="avatar" multiple> <input type="submit" value="上傳"> </form>這裡的參考程式碼只處理一張圖片,多張圖片迴圈處理就可以了:

class UploadController extends Controller {

async file() {

const { ctx } = this;

const dest = '/public/upload/';

const file = ctx.request.files[0];

console.log(ctx.request.files);

let to = path.dirname(__dirname) + dest + path.basename(file.filepath);

// 處理檔案,比如上傳到雲端 或 放到指定的目錄

await fs.copyFileSync(file.filepath, to);

fs.unlinkSync(file.filepath);

console.log(dest);

// 返回圖片路徑

let cluster = this.app.config.cluster.listen;

ctx.body = `http://${cluster.hostname}:${cluster.port}${dest}${path.basename(file.filepath)}`;

}

}

7.Cookie

通過 ctx.cookies可以在 Controller 中便捷、安全的設定和讀取 Cookie。

class CookieController extends Controller { async add() { const ctx = this.ctx; let count = ctx.cookies.get('count'); count = count ? Number(count) : 0; ctx.cookies.set('count', ++count); ctx.body = count; } async remove() { const ctx = this.ctx; const count = ctx.cookies.set('count', null); ctx.status = 204; }}

需要注意的是,cookie預設不支援中文,可以嘗試轉碼,如encodeURI('中文egg'),然後再轉回來decodeURI(ctx.cookies.get('username'));也可以通過加密的方式處理。

清除cookie把值設定為null即可。

在設定cookie時有個物件型別的可選引數,可以對cookie進行相關設定:

maxAge: 設定cookie的有效期,單位毫秒,預設瀏覽器關閉消失;

httpOnly:設定cookie是否允許js訪問,預設true,不允許;

overwrite:如果設定為true,相同的鍵值對會被覆蓋,否則傳送兩個;

signed:如果為true表示對cookie進行簽名,不是加密,只是防止被篡改,注意在獲取的時候也要提供該設定進行匹配;

encrypt:是否加密,true加密後客戶端看不到明文,只能在伺服器端獲取,注意在獲取的時候也要提供該設定進行匹配;

8.Session

Session 的使用方法非常直觀,直接讀取或者修改就可以,如果要刪除它,直接將它賦值為 null:

class SessionController extends Controller { async deleteSession() { this.ctx.session = null; }};

注意:設定 session 屬性時不要以 _ 開頭,不能為 isNew

Session預設配置如下:

 exports.session = {         key: 'EGG_SESS',         maxAge: 24 * 3600 * 1000, // 1 天         httpOnly: true,         encrypt: true,};

也可以針對性設定有效期:

 // 如果使用者勾選了 `記住我`,設定 30 天的過期時間if (rememberMe) ctx.session.maxAge = ms('30d');

重置session的有效期:當用戶 Session 的有效期僅剩下最大有效期一半的時候

 // config/config.default.jsmodule.exports = {  session: {         renew: true,  },};

9.呼叫service

在 Controller 中可以呼叫任何一個 Service 上的任何方法,同時 Service 是懶載入的,只有當訪問到它的時候框架才會去例項化它。

 // 呼叫 service 進行業務處理const res = await ctx.service.post.create(req);

10.傳送HTTP響應

i. 設定status

// 設定狀態碼為 201this.ctx.status = 201;

ii. 設定body

ctx.body 是 ctx.response.body 的簡寫,不要和 ctx.request.body 混淆了;

// 響應內容this.ctx.body = '<html><h1>Hello</h1></html>';

iii. JSONP

app.jsonp() 提供的中介軟體來讓一個 controller 支援響應 JSONP 格式的資料。在路由中,我們給需要支援 jsonp 的路由加上這個中介軟體:

// app/router.jsmodule.exports = app => {  const jsonp = app.jsonp();  app.router.get('/api/posts/:id', jsonp, app.controller.posts.show);  app.router.get('/api/posts', jsonp, app.controller.posts.list);};

在 Controller 中,只需要正常編寫即可。使用者請求對應的 URL 訪問到這個 controller 的時候,如果 query 中有 _callback=fn 引數,將會返回 JSONP 格式的資料,否則返回JSON格式的資料。

可配置:

// config/config.default.jsexports.jsonp = {  callback: 'callback', // 識別 query 中的 `callback` 引數  limit: 100, // 函式名最長為 100 個字元};

iv. 重定向

Ø ctx.redirect(url) 如果不在配置的白名單域名內,則禁止跳轉。

Ø ctx.unsafeRedirect(url) 不判斷域名,直接跳轉,一般不建議使用,明確了解可能帶來的風險後使用。

使用者如果使用ctx.redirect方法,需要在應用的配置檔案中做如下配置:

// config/config.default.jsexports.security = {  domainWhiteList:['.domain.com'],  // 安全白名單,以 . 開頭};

若使用者沒有配置 domainWhiteList 或者 domainWhiteList陣列內為空,則預設會對所有跳轉請求放行,即等同於ctx.unsafeRedirect(url)

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 基於SpringBoot整合豐富的第三方APP後臺管理系統