Skip to main content

后端登录功能使用装饰器与反射优化实例

//tsconfig.json
"experimentalDecorators": true,
"emitDecoratorMetadata": true,

npm install reflect-metadata -S





// controller/LoginController.ts

import Express, { Router, Request, Response, NextFunction } from 'express'
import { getResponseData, checkLogin } from '../utils/index'

interface RequestWithBody extends Request {
body: {
[key: string]: string | undefined
}
}

const homePageHtml = `
<html>
<body>
<a href="/showData" >展示数据</a>
<a href="/logout" >退出登录</a>
</body>
</html>
`
const loginPageHtml = `
<html>
<body>
<form method="post" action="/login">
<input type="password" name="password" />
<button>登陆</button>
</form>
</body>
</html>
`

export class LoginController {


home(req: Request, res: Response, next: NextFunction) {

if (req.session?.isLogin) {
res.send(homePageHtml);
} else {
res.send(loginPageHtml);
}

}

login(req: RequestWithBody, res: Response) {
if (req.session?.isLogin) {
res.json(getResponseData(false, '已经登录过'))
} else {
if (req.body?.password === '123456' && req.session) {
req.session.isLogin = true;
res.json(getResponseData(true))
} else {
res.json(getResponseData(false, '登录失败'));
}
}
}

logout(req: Request, res: Response) {

if (req.session) {
req.session.isLogin = undefined;
}
res.json(getResponseData(true));
}
}


//contorller/DataController.ts

import { Request, Response } from 'express'
import { getResponseData, checkLogin } from '../utils/index'
import { get, use, controller } from '../decorator/'
import * as Data from '../utils/data.json'

@controller('/')
export class DataController {

@get('/showData')
@use(checkLogin)
router(req: Request, res: Response) {

res.json(getResponseData(Data))

}
}








//decorator目录:

controller 对控制器定义的路由统一收集,然后统一定义路由

import router from '../router';
import { RequestHandler } from 'express'
import { Methods } from './request'

export function controller(root: string) {
return function <T extends { new(...args: any[]): any }>(construct: T) {
for (let key in construct.prototype) {
let pathStr: string = Reflect.getMetadata('path', construct.prototype, key)
let method: Methods = Reflect.getMetadata('method', construct.prototype, key);
let middlewares:RequestHandler[] = Reflect.getMetadata('middlewares', construct.prototype, key) || [];
if (root) {
pathStr = root == '/' ? pathStr : root + pathStr
}

if (pathStr && method) {
router[method](pathStr, ...middlewares, construct.prototype[key]);
}
}
}
}













use 对处理方法,使用中间件

import { RequestHandler} from 'express'
export function use(middleware: RequestHandler) {
return function (target: any, key: string, dec: PropertyDescriptor) {
let middlewares = Reflect.getMetadata('middlewares', target, key) || [];
middlewares.push(middleware);
Reflect.defineMetadata('middlewares', middlewares, target, key);
}
}






request 获取处理方法上的定义的请求方式,请求路由

import 'reflect-metadata'

export enum Methods {
GET = 'get',
POST = 'post'
}

function requestMethods(methods:Methods) {
return function (path: string) {

return function (target: any, key: string, dec: PropertyDescriptor) {
Reflect.defineMetadata('path', path, target, key);
Reflect.defineMetadata('method', methods, target, key);
}
}
}

export const get = requestMethods(Methods.GET)
export const post = requestMethods(Methods.POST)



//router.ts

import { Router } from 'express';

export default Router();


//index.ts
引入路由,添加控制器

import express, { } from 'express';
import bodyParser from 'body-parser'
import cookieSession from 'cookie-session'
import './controller/LoginController'
import './controller/DataController'
import router from './router'

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));

app.use(cookieSession({
name: 'session',
keys: ['typescript-api'],
maxAge: 24 * 60 * 60 * 10000
}))
app.use(router);
app.listen(8000, () => {
console.log("server success!");
})