為了將面向過(guò)程的代碼改造成面向?qū)ο蟮拇a排宰。
將現(xiàn)有的代碼進(jìn)行改造。
首先將login的邏輯進(jìn)行遷移:
創(chuàng)建LoginController.ts
,并將代碼遷移過(guò)來(lái),先遷移具體邏輯刻像,不管路由
class LoginController{
home(req:Request,res:Response){
const isLogin = req.session ? req.session.login : false
if(isLogin){
res.send(`
<body>
<a href='/logout'>logout</a>
<a href='/getData'>getData</a>
<a href='/showData'>showData</a>
</body>
`)
}else{
const formHtml = `
<body>
<form method='POST' action='/login'>
<input type='password' name='password'>
<button>Submit</button>
</form>
</body>
`
res.send(formHtml)
}
}
}
// LoginController.ts
- 創(chuàng)建一個(gè)路由的控制器,并通過(guò)原數(shù)據(jù)的方式亭引,將路徑保存在這個(gè)方法之上
//controller類的裝飾器
function controller(target:any){
for(let key in target.prototype){
//打印出綁定的路徑
console.log(Reflect.getMetadata('path',target.prototype,key))
// ‘/’
}
}
//路由的裝飾器
function get(path:string){
return function(target:any,key:string){
Reflect.defineMetadata('path',path,target,key)
}
}
@controller
class LoginController{
@get('/')
home()
...
}
在完成基礎(chǔ)的裝飾器之后绎速,我們需要讓LoginController
通過(guò)裝飾器實(shí)現(xiàn)路由的功能
- 根據(jù)在原數(shù)據(jù)上的路徑,如果路徑存在,自動(dòng)生成項(xiàng)目的路由
export function controller(target:any){
for(let key in target.prototype){
const path = Reflect.getMetadata('path',target.prototype,key)
if(path){
const handler = target.prototype[key]
router.get(path,handler)
}
}
}
- 為了能自動(dòng)生成路由焙蚓,只需要引入
LoginController
這個(gè)文件纹冤,就能執(zhí)行洒宝,并生成路由 - 將所有的get請(qǐng)求遷移過(guò)來(lái)
class LoginController{
@get('/')
home(req:Request,res:Response){
const isLogin = req.session ? req.session.login : false
if(isLogin){
res.send(`
<body>
<a href='/logout'>logout</a>
<a href='/getData'>getData</a>
<a href='/showData'>showData</a>
</body>
`)
}else{
const formHtml = `
<body>
<form method='POST' action='/login'>
<input type='password' name='password'>
<button>Submit</button>
</form>
</body>
`
res.send(formHtml)
}
}
@get('/logOut')
logOut(req:Request,res:Response){
if(req.session){
req.session.login = undefined
}
res.json(getResponseData(true));
}
}
- 接下來(lái)再遷移一下原有的post請(qǐng)求
//LoginController.ts
@post('/login')
login(req:Request,res:Response){
const isLogin = req.session ? req.session.login : false
if(isLogin){
res.json(getResponseData(false, '已經(jīng)登陸過(guò)'));
}else{
if(req.body.password === '123' && req.session){
req.session.login = true
res.json(getResponseData(true));
}else{
res.json(getResponseData(false, 'login failed'));
}
}
}
//decorator.ts
export function post(path:string){
return function(target:any,key:string){
Reflect.defineMetadata('path',path,target,key)
}
}
- 但是原有的裝飾器已滿足不了新的需求,因?yàn)樵械难b飾器無(wú)法辨別出post和get請(qǐng)求萌京,所以雁歌,需要在元數(shù)據(jù)上綁定一個(gè)請(qǐng)求方法
enum Method{
get = 'get',
post = 'post',
put = 'put',
del = 'delete'
}
export function controller(target:any){
for(let key in target.prototype){
const path = Reflect.getMetadata('path',target.prototype,key)
//利用枚舉類型對(duì)請(qǐng)求方法進(jìn)行定義
const method:Method = Reflect.getMetadata('method',target.prototype,key)
const handler = target.prototype[key]
if(path&&method&&handler){
//往router上綁定方法
router[method](path,handler)
}
}
}
export function post(path:string){
return function(target:any,key:string){
Reflect.defineMetadata('path',path,target,key)
Reflect.defineMetadata('method','post',target,key)
}
}
- 同時(shí)也可以看到,生成請(qǐng)求方法裝飾器的函數(shù)有大量?jī)?nèi)容冗余知残,可以利用工廠模式優(yōu)化一代碼
function methodFactory(type:string){
return function(path:string){
return function(target:any,key:string){
Reflect.defineMetadata('path',path,target,key)
Reflect.defineMetadata('method',type,target,key)
}
}
}
export const get = methodFactory('get')
export const post = methodFactory('post')
export const put = methodFactory('put')
- 對(duì)使用了中間件的路由的裝飾器
- middleware類型:
RequestHandler
- middleware類型:
//在方法的裝飾器上綁定
export function controller(target:any){
for(let key in target.prototype){
const path = Reflect.getMetadata('path',target.prototype,key)
const method:Method = Reflect.getMetadata('method',target.prototype,key)
const middleware = Reflect.getMetadata('middleware',target.prototype,key)
const handler = target.prototype[key]
if(path&&method&&handler){
//如果有中間件就使用中間件
if(middleware){
router[method](path,middleware,handler)
}else{
router[method](path,handler)
}
}
}
}
//中間件的裝飾器
export function use(middleware:RequestHandler){
return function(target:any,key:string){
Reflect.defineMetadata('middleware',middleware,target,key)
}
}
優(yōu)化項(xiàng)目結(jié)構(gòu)
- 將router從decorator中拆分出來(lái)
import {Router} from 'express';
export const router = Router()
- 按職責(zé)對(duì)decorator進(jìn)行進(jìn)一步拆分
- use.ts 處理中間件相關(guān)的裝飾器
import {RequestHandler} from 'express'; export function use(middleware:RequestHandler){ return function(target:any,key:string){ Reflect.defineMetadata('middleware',middleware,target,key) } }
- request.ts 處理請(qǐng)求相關(guān)的裝飾器
- use.ts 處理中間件相關(guān)的裝飾器
enum Methods{
get = 'get',
post = 'post',
put = 'put',
del = 'delete'
}
function methodFactory(type:Methods){
return function(path:string){
return function(target:any,key:string){
Reflect.defineMetadata('path',path,target,key)
Reflect.defineMetadata('method',type,target,key)
}
}
}
export const get = methodFactory(Methods.get)
export const post = methodFactory(Methods.post)
export const put = methodFactory(Methods.put)
- controller.ts 處理controller類的裝飾器
import {Router,Request,Response, NextFunction,RequestHandler} from 'express';
import {router} from '../router'
enum Methods{
get = 'get',
post = 'post',
put = 'put',
del = 'delete'
}
export function controller(target:any){
for(let key in target.prototype){
const path = Reflect.getMetadata('path',target.prototype,key)
const method:Methods = Reflect.getMetadata('method',target.prototype,key)
const middleware = Reflect.getMetadata('middleware',target.prototype,key)
const handler = target.prototype[key]
if(path&&method&&handler){
if(middleware){
router[method](path,middleware,handler)
}else{
router[method](path,handler)
}
}
}
}
最終項(xiàng)目目錄:
├── data
│ └── course.json
├── package-lock.json
├── package.json
├── src
│ ├── analyzer.ts
│ ├── analyzerB.ts
│ ├── controller
│ │ ├── CrowllerController.ts
│ │ ├── LoginController.ts
│ │ └── decoratorOld.ts
│ ├── crowller.ts
│ ├── customer.d.ts
│ ├── decorator
│ │ ├── controller.ts
│ │ ├── index.ts
│ │ ├── request.ts
│ │ └── use.ts
│ ├── index.ts
│ ├── responseHandler.ts
│ ├── router.ts
│ └── routerOld.ts
└── tsconfig.json