Typescript node starter 3. App Router Controller
Request
request对象表示HTTP请求,并具有请求query字符串、参数、body、HTTP headers等的属性。除了添加新的属性和方法外,还包含原型的属性和方法。
随着系列文章的发布,我们将继续研究使用request对象;
Response
response对象表示程序在接收到HTTP请求时发送HTTP响应。它最重要的方法就是send,它发送HTTP响应,所以客户端能够接收到它。send函数接受不同类型的数据,例如string,object,数组或缓冲区。send使用数据结束响应过程,也可以使用end函数结束响应过程。
与request对象一样,我们将继续深入研究和使用它。
app.get('/', (request, response) => {
response.send({
hostname: request.hostname,
path: request.path,
method: request.method,
});
});
Controllers
创建一个Express应用的常见方法叫做mvc。controller是mvc的关键组件,它包含了应用程序中处理客户端请求的主要逻辑。为了使项目具有良好的可读性,我创建了一个app类,并且使用外置路由挂载相应的controller函数。
在server脚本中加载应用,监听端口。 src/server.ts
app.listen(process.env.PORT || 3001, () => {
logger.info(`Server running at http://localhost:${process.env.PORT} in ${process.env.NODE_ENV}`);
});
下面代码定义了app类,通过构造函数创建express应用,注册中间件,初始化路由器,连接数据库。src/app.ts:
class App {
app: express.Application = express();
private _routes: Router;
constructor(mongoUrl: string) {
this.app = express();
this.initializeStaticFolder(this.app);
this.initializeMiddlewares(this.app);
this._routes = new Router();
this._routes.initializeRouter(this.app);
this.mongoSetup(mongoUrl);
this.app.use((request: Request, response: Response) => {
return response.status(404).json({ code: -1, data: null, msg: "Notfound" })
});
}
//初始化中间件
private initializeMiddlewares = (app: express.Application): void =>{
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
}
//初始化静态文件夹
private initializeStaticFolder = (app: express.Application): void =>{
const folder = "assets";
const fileFolder = path.resolve(folder);
app.use(express.static(fileFolder))
}
//连接数据库
private mongoSetup = (connStr: string): void => {
mongoose.connect(connStr, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false }).then(
() => { logger.info("MongoDB connection success!"); }
).catch(
(err) => { logger.error("MongoDB connection error. Please make sure MongoDB is running. " + err); }
);
}
}
export default new App(MONGODB_URI).app;
下面代码定义了应用程序的总路由器类,通过构造函数实例化外置路由和控制器;定义初始化路由函数,将express应用程序传递给外置路由器。src/router.ts:
export class Router {
private _clientRouter: ClientRouter;
constructor() {
const clientController = new ClientController();
this._clientRouter = new ClientRouter(clientController);
}
//registered routing.
initializeRouter = (app): void => {
this._clientRouter.router(app);
}
}
下面的代码定义了client的外置路由器,涉及到了client的增删改查功能。src/auth/client/clientRouter.ts
export class ClientRouter {
private _clientController: ClientController;
private _router: Router;
constructor(clientController: ClientController) {
this._clientController = clientController;
this._router = Router();//创建一个express的外置路由
this.initRouter(this._router);
}
//配置路由与controller.
private initRouter = (router: Router): void => {
router.route("")
.get(this._clientController.getClients)
.post(this._clientController.create);
router.route("/:id")
.patch(this._clientController.update)
.delete(this._clientController.delete);
}
//将外置路由配置给express应用程序
router = (app: express.Application): void => {
app.use("/api/v1/admin/clients", this._router);
}
}
下列代码定义了client的控制器类,该类中的函数要被传递给clientRouter使用,上下文发生了变化,所以采用箭头函数保证this的指向正确。src/auth/client/clientController.ts
export class ClientController
{
private _iclientRepository: IClientRepository;
constructor(iClientRepository: IClientRepository)
{
this._iclientRepository = iClientRepository;
} create = async(req: Request, res: Response, next: NextFunction): Promise<void | Response>=>{
try
{
const { clientId, clientName, grants } = req.body;
const body = { clientId, clientName, grants };
const client = await this._iclientRepository.create(body);
if(client){
return this.responseSuccess(201, client, "Created.", res);
}
else{
return this.responseWarn(200, {code: ErrCode.CLIENTID_OR_CLIENTNAME_EXISTS}, "ClientName or clientId field is already exists.", res);
}
}
catch (e)
{
logger.error(e);
next(e);
} } getClients = async(req: Request, res: Response, next: NextFunction): Promise<void | Response>=>{
try
{
let pageSize = req.query.pageSize || 5;
let page = req.query.page || 1; pageSize = (Number)(pageSize);
page = (Number)(page);
const clients = await this._iclientRepository.getClients(page, pageSize);
if(clients){
return this.responseSuccess(200, clients, `${clients.length} client.`, res);
}
else{
return this.responseWarn(200, {code: ErrCode.CLIENT_NOCONTENT}, "0 client.", res);
}
}
catch (e)
{
logger.error(e);
next(e);
}
} update = async(req: Request, res: Response, next: NextFunction): Promise<void | Response>=>{
try
{
const { id } = req.params;
const body = req.body;
const clientName = body.clientName; if (body.clientId || body.clientId === "") {
delete body.clientId;
}
if (body.clientSecret || body.clientSecret === "") {
delete body.clientSecret;
} const client = await this._iclientRepository.update(id, clientName, body);
if(client){
return this.responseSuccess(200, client, `${client.clientName} has been updated.`, res);
}
else{
return this.responseWarn(200, {code: ErrCode.INVALID_CLIENT}, "The client is notfound or clientName/clientId field is already exists.", res);
}
}
catch (e)
{
logger.error(e);
next(e);
}
} delete = async(req: Request, res: Response, next: NextFunction): Promise<void | Response>=>{
try
{
const { id } = req.params;
const client = await this._iclientRepository.delete(id);
if(client){
return this.responseSuccess(204, null, "deleted.", res);
}
else{
return this.responseWarn(200, {code: ErrCode.CLIENT_NOTFOUND}, "The client is notfound.", res);
}
}
catch (e)
{
logger.error(e);
next(e);
}
} private responseSuccess = (statusCode: number, data: object, msg: string, res: Response): void =>{
res.status(statusCode).json({
code: 0,
data,
msg
});
} private responseWarn = (statusCode: number, data: object, msg: string, res: Response): void =>{
res.status(statusCode).json({
code: 1,
data,
msg
});
}
}
Typescript node starter 3. App Router Controller的更多相关文章
- Typescript node starter 2.Router Middleware
Router 路由器对象是中间件和路由的一个独立实例.可以将它视为一个“迷你应用程序”,仅能够执行中间件和路由功能.每个Express应用程序都有一个内置的应用程序路由器. 路由器的行为类似于中间件本 ...
- Typescript node starter 1.Express Typescript
启动项目 Express 是一个nodejs框架,用于构建Web后端应用程序.它非常的灵活,你可以用你喜欢的方式去使用他.在这个系列文章里,记录了我使用typescript express去构建一个w ...
- Cannot declare class app\home\controller\Cases because the name is already in use
Cannot declare class app\home\controller\Cases because the name is already in use 命名空间冲突了 use 模型类的时候 ...
- thinkphp报错Call to undefined method app\index\controller\Index::fetch()
因为要写一个系统,所以又重新下载了thinkphp,然后安装了一下.回忆起这个问题很容易让新手朋友费解.会出现如下报错:Call to undefined method app\index\contr ...
- SAP Netweaver的负载均衡消息服务器 vs CloudFoundry的App Router
Message server for ABAP Netweaver SAP传统应用经典的三层架构: 起到负载均衡的消息服务器(Message Server)在图中没有得到体现.然后,消息服务器在我们每 ...
- 控制器不存在:app\admin\controller\Document
控制器不存在:app\admin\controller\Document 报错: 控制器不存在:app\admin\controller\Document 但是我在代码里面找了半天没出现Documen ...
- Thinkphp6框架学习:($this->error()undefined)Call to undefined method app\index\controller\Admin::error()
最近在使用Thinkphp6框架的时候,想做一个初始化来验证登录状态. 当没有Session::get(‘adminUid’)的时候就应该跳转到admin\adminLogin的方法中,和以前Tp5的 ...
- tp6 控制器不存在:app\index\controller\Index
tp6 控制器不存在:app\index\controller\Index config/app.php 修改如下 'auto_multi_app' => true,
- AngularJS之手动加载模块app和controller
使用ng的页面中一般都是使用模块自动加载,页面的结构一般是这样的 加载angularjs脚本 加载业务代码脚本(或者写在script标签中) html结构代码(带有ng指令) 就像这样 app.htm ...
随机推荐
- 使样式只在webkit内核生效
@media screen and (-webkit-min-device-pixel-ratio:0){ .do someting{ } } 使用媒体查询,制定样式
- 来自马铁大神的Spark10年回忆录
本篇分享来自Martei在Spark AI Submit 2020的开场分享. 马铁是谁 什么!你不知道马铁是谁?Martei Zaharia(说实话,不知道谁给起的中文名字叫马铁,跟着叫就是了),现 ...
- Python无限循环
Python 无限循环:在 while 循环语句中,可以通过让判断条件一直达不到 False ,实现无限循环. 条件表达式: # var = 1 # while var == 1: # 表达式永远为 ...
- More JOIN operations -- SQLZOO
The JOIN operation 注意:where语句中对表示条件的需要用单引号, 下面的译文使用的是有道翻译如有不正确,请直接投诉有道 01.List the films where the y ...
- Python os.chmod() 方法
概述 os.chmod() 方法用于更改文件或目录的权限.高佣联盟 www.cgewang.com 语法 chmod()方法语法格式如下: os.chmod(path, mode) 参数 path - ...
- RectTransform的localPosition与anchoredPosition(3D)的区别
RectTransform继承自Transform,用于描述矩形的坐标(Position),尺寸(Size),锚点(anchor)和中心点(pivot)等信息,每个2D布局下的元素都会自动生成该组件. ...
- NOI Online 游戏 树形dp 广义容斥/二项式反演
LINK:游戏 还是过于弱鸡 没看出来是个二项式反演,虽然学过一遍 但印象不深刻. 二项式反演:有两种形式 一种是以恰好和至多的转换 一种是恰好和至少得转换. 设\(f_i\)表示至多的方案数 \(g ...
- 4.13 省选模拟赛 传销组织 bitset 强连通分量 分块
考试的时候昏了头 没算空间 这道题我爆零了.值得注意的是 一般认为bitset的空间是 int 的1/w倍 对于那m条边 无论如何构造 这m条关系都是存在的 题目其实是想让我们用这m条关系来计算给出的 ...
- LeetCode刷题时引发的思考:Java中ArrayList存放的是值还是引用?
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 今天我在刷LeetCode ...
- 加密模块hashlib模块(* *)
用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 越往后加密算法越复杂,这些算法都是不可逆的,MD5 算法 ...