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 ...
随机推荐
- DJANGO-天天生鲜项目从0到1-014-订单-订单评论
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- Dicom文件基本操作
官方文档 网址:https://github.com/fo-dicom/fo-dicom托管在github上. 官方例子 Dicom文件基本操作 var file = DicomFile.Open(@ ...
- leetcode题库练习_两数之和
题目:两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元素不能 ...
- xctf-pwn pwn200
刚看完题目觉得和前面的level3差不多,只是没有给libc而已... 看完大佬的exp之后整个人都不好了.....果然我还是太菜了 32位开了NX sub_8048484,read函数,明显的栈溢出 ...
- springboot2.2 集成 activity6 请假完整示例
新手学习记录.写在springboot test 示例 示例代码地址看结尾.后面有带页面的示例. SpringBoot Test无页面简单示例 员工请假流程 员工发起申请,附带请假信息(请假几天) ...
- Python定位模块_PYTHONPATH变量
Python定位模块: 导入模块时,系统会根据搜索路径进行寻找模块: 1.在程序当前目录下寻找该模块 2.在环境变量 PYTHONPATH 中指定的路径列表寻找 3.在 Python 安装路径中寻找 ...
- Redis 的 KEYS 命令不能乱用啊
KESY 命令 时间复杂度: O(N) , 假设Redis中的键名和给定的模式的长度有限的情况下,N为数据库中key的个数. Redis Keys 命令用于查找所有符合给定模式 pattern 的 k ...
- PHP xml_parser_create() 函数
定义和用法 xml_parser_create() 函数创建 XML 解析器.高佣联盟 www.cgewang.com 如果成功,该函数则返回可被其它 XML 函数使用的资源句柄.如果失败,则返回 F ...
- PHP strspn() 函数
实例 返回在字符串 "Hello world!" 中包含字符 "kHlleo" 的数目: <?php高佣联盟 www.cgewang.comecho st ...
- html实现a元素href的URL链接自动刷新或新窗口打开
有时我们想实现这样一个功能,点击一个链接,如果这个链接浏览器已经打开过,则刷新已经打开的链接窗口:如果这个链接没有打开过,则使用新窗口打开这个链接页面. 这是一个非常好的体验增强功能,可以有效避免浏览 ...