egg直接取req_Egg服务器基础功能
1. 框架約定目錄規(guī)則
1.1 app/router.js:用于配置URL路由規(guī)則;
1.2 app/controller/** :用于解析用戶的輸入,處理后返回相應(yīng)的結(jié)果;
1.3 app/service/**: 用于編寫業(yè)務(wù)邏輯層;
1.4 app/public/**: 用于放置靜態(tài)資源;
1.5 config/config.{env}.js: 用于編寫配置文件;
1.6 config/plugin.js 用于配置需要加載的插件;
2.內(nèi)置對象
1. Application:全局應(yīng)用對象,在一個應(yīng)用中,只會實例化一個對象;
在繼承于 Controller, Service 基類的實例中,可以通過 this.app 訪問到 Application 對象。
2. Request & Response:可以在 Context 的實例上獲取到當前請求的 Request(ctx.request) 和 Response(ctx.response) 實例;
3. Controller:推薦所有的 Controller 都繼承于該基類實現(xiàn)。該基類屬性有:
ctx - 當前請求的 Context 實例。
app - 應(yīng)用的 Application 實例。
service - 應(yīng)用所有的 service。
4. Service:推薦所有的Service都繼承該基類。
Service基類屬性和 Controller 基類屬性一致。
3.路由Router
路由是描述請求URL和具體承擔執(zhí)行動作的Controller的對應(yīng)。說的直白點,就是用戶訪問不同的路徑時應(yīng)該有不同的Controller去響應(yīng)不同的內(nèi)容。
4.控制器Controller
1. 控制器的定義以及和路由的關(guān)聯(lián)
Controller負責解析用戶的輸入,處理后返回響應(yīng)的結(jié)果。所有的Controller 文件都必須放在 app/controller目錄下,支持多級目錄,訪問時可以通過目錄名級聯(lián)訪問。如將Controller代碼放到 app/controller/sub/post.js 中,則可以在 router 中這樣使用:
// app/router.js
module.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.獲取提交的數(shù)據(jù)
接收GET請求的數(shù)據(jù):ctx.request.query 和 ctx.query.id;
接收POST請求的數(shù)據(jù):ctx.request.body,而不是 ctx.body;post請求時,會有安全驗證問題,簡單的處理方式是關(guān)閉安全驗證:
// config/config.default.js
// 配置安全驗證
config.security = {
csrf: {
enable: false,
ignoreJSON: true,
}
}
Post數(shù)據(jù)默認大小是100kb,如需調(diào)整可在 config/config.default.js 中覆蓋框架的默認值:
module.exports = {? ??????????????? bodyParser: {??? ????????????????????? jsonLimit: '1mb',??? ????????????????????? formLimit: '1mb',? ??????????????? },};接收路由參數(shù):
// 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.js
exports.multipart = {
mode: 'file',
};
然后,你就可以參考下面的代碼了:
這里的參考代碼只處理一張圖片,多張圖片循環(huán)處理就可以了:
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 中便捷、安全的設(shè)置和讀取 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默認不支持中文,可以嘗試轉(zhuǎn)碼,如encodeURI('中文egg'),然后再轉(zhuǎn)回來decodeURI(ctx.cookies.get('username'));也可以通過加密的方式處理。
清除cookie把值設(shè)置為null即可。
在設(shè)置cookie時有個對象類型的可選參數(shù),可以對cookie進行相關(guān)設(shè)置:
maxAge: 設(shè)置cookie的有效期,單位毫秒,默認瀏覽器關(guān)閉消失;
httpOnly:設(shè)置cookie是否允許js訪問,默認true,不允許;
overwrite:如果設(shè)置為true,相同的鍵值對會被覆蓋,否則發(fā)送兩個;
signed:如果為true表示對cookie進行簽名,不是加密,只是防止被篡改,注意在獲取的時候也要提供該設(shè)置進行匹配;
encrypt:是否加密,true加密后客戶端看不到明文,只能在服務(wù)器端獲取,注意在獲取的時候也要提供該設(shè)置進行匹配;
8.Session
Session 的使用方法非常直觀,直接讀取或者修改就可以,如果要刪除它,直接將它賦值為 null:
class SessionController extends Controller {async deleteSession() {this.ctx.session = null;
}
};
注意:設(shè)置 session 屬性時不要以 _ 開頭,不能為 isNew
Session默認配置如下:
exports.session = {? ?????? key: 'EGG_SESS',? ?????? maxAge: 24 * 3600 * 1000, // 1 天? ?????? httpOnly: true,? ?????? encrypt: true,};也可以針對性設(shè)置有效期:
// 如果用戶勾選了 `記住我`,設(shè)置 30 天的過期時間if (rememberMe) ctx.session.maxAge = ms('30d');重置session的有效期:當用戶 Session 的有效期僅剩下最大有效期一半的時候
// config/config.default.jsmodule.exports = {? session: {??? ???? renew: true,? },};9.調(diào)用service
在 Controller 中可以調(diào)用任何一個 Service 上的任何方法,同時 Service 是懶加載的,只有當訪問到它的時候框架才會去實例化它。
// 調(diào)用 service 進行業(yè)務(wù)處理const res = await ctx.service.post.create(req);10.發(fā)送HTTP響應(yīng)
i. 設(shè)置status
// 設(shè)置狀態(tài)碼為 201this.ctx.status = 201;ii. 設(shè)置body
ctx.body 是 ctx.response.body 的簡寫,不要和 ctx.request.body 混淆了;
// 響應(yīng)內(nèi)容this.ctx.body = 'Hello
';iii. JSONP
app.jsonp() 提供的中間件來讓一個 controller 支持響應(yīng) JSONP 格式的數(shù)據(jù)。在路由中,我們給需要支持 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 中,只需要正常編寫即可。用戶請求對應(yīng)的 URL 訪問到這個 controller 的時候,如果 query 中有 _callback=fn 參數(shù),將會返回 JSONP 格式的數(shù)據(jù),否則返回JSON格式的數(shù)據(jù)。
可配置:
// config/config.default.jsexports.jsonp = {? callback: 'callback', // 識別 query 中的 `callback` 參數(shù)? limit: 100, // 函數(shù)名最長為 100 個字符};iv. 重定向
? ctx.redirect(url) 如果不在配置的白名單域名內(nèi),則禁止跳轉(zhuǎn)。
? ctx.unsafeRedirect(url) 不判斷域名,直接跳轉(zhuǎn),一般不建議使用,明確了解可能帶來的風險后使用。
用戶如果使用ctx.redirect方法,需要在應(yīng)用的配置文件中做如下配置:
// config/config.default.jsexports.security = {? domainWhiteList:['.domain.com'],? // 安全白名單,以 . 開頭};若用戶沒有配置 domainWhiteList 或者 domainWhiteList數(shù)組內(nèi)為空,則默認會對所有跳轉(zhuǎn)請求放行,即等同于ctx.unsafeRedirect(url)
總結(jié)
以上是生活随笔為你收集整理的egg直接取req_Egg服务器基础功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写一个C程序,实现以下功能:输入n个人
- 下一篇: 更改应用程序图标_苹果更新 TestFl