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 ...
随机推荐
- Java 并发队列 BlockingQueue
BlockingQueue 开篇先介绍下 BlockingQueue 这个接口的规则,后面再看其实现. 首先,最基本的来说, BlockingQueue 是一个先进先出的队列(Queue),为什么说是 ...
- iOS倒计时button闪烁
v _button.titleLabel.text = [NSString stringWithFormat:@"%d后重发",t]; [_button setTitle:[NSS ...
- myBatis源码解析-日志篇(1)
上半年在进行知识储备,下半年争取写一点好的博客来记录自己源码之路.在学习源码的路上也掌握了一些设计模式,可所谓一举两得.本次打算写Mybatis的源码解读. 准备工作 1. 下载mybatis源码 下 ...
- JavaFX让UI更美观-CSS样式
相对于Swing来说,JavaFX在UI上改善了很多,不仅可以通过FXML来排版布局界面,同时也可以通过CSS样式表来美化UI. 其实在开发JavaFX应用的时候,可以将FXML看做是HTML,这样跟 ...
- Python2.7 PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed 问题解决
# 报错信息 PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.insta ...
- 6-Pandas之缺失值处理
一.了解缺失值 通常使用 NA('not available')来代指缺失值 在Pandas的数据结构中,缺失值使用 NaN('Not a Number')进行标识 除了汇总统计方法,还可以使用isn ...
- PHP is_callable() 函数
is_callable() 函数用于检测函数在当前环境中是否可调用.高佣联盟 www.cgewang.com is_callable() 函数验证变量的内容能否作为函数调用. 这可以检查包含有效函数名 ...
- P2569 [SCOI2010]股票交易 dp 单调队列优化
LINK:股票交易 题目确实不算难 但是坑点挺多 关于初值的处理问题我就wa了两次. 所以来谢罪. 由于在手中的邮票的数量存在限制 且每次买入卖出也有限制. 必然要多开一维来存每天的邮票数量. 那么容 ...
- Lambda表达式运行原理
目录 一.创建测试样例 二.利用Java命令编译分析 三.文末 JDK8引入了Lambda表达式以后,对我们写代码提供了很大的便利,那么Lambda表达式是如何运用简单表示来达到运行效果的呢?今天,我 ...
- 【CF115E】Linear Kingdom Races 题解(线段树优化DP)
前言:前辈讲课时设的状态还是有些繁琐,感觉题解设的状态更简洁. -------------- 题目链接 题目大意:给定$n$条道路和$m$场比赛,每个道路修建需要$c_i$,每场比赛需要使用$[l_i ...