NestJS下的CQRS实现 - Query部分
本文旨在介绍NestJS下CQRS(命令查询职责分离)的实现。NestJS的确是个强大的NodeJS框架,支持了绝大多数现在流行的技术栈。至于什么是CQRS模式,请大家自行查阅。废话不多说,直接上代码。
1: 新建项目
nest new cqrs-demo
2: 安装CQRS依赖
npm install --save @nestjs/cqrs
3: 添加comments模块
nest g module comments
4: 添加Query相关代码
CQRS的核心,除了Command与Query的分离,还有Controller层与Handler层的解耦。以往的MVC架构中,Controller层会实例化Service,比如UserService,CommentService。Service实例提供了数据库操作逻辑。 这就是Controller与Service的紧耦合。 NestJS的CQRS框架通过QueryBus/CommandBus(.net的CQRS框架中称为Mediator)实现了Controller与事件处理服务的解耦。
且看以下代码
comment.model.ts
export class Comment {
private readonly id: string;
constructor(_id: string) {
this.id = _id;
console.log(`constructor model - id: ${this.id}`);
}
}
get-comment.handler.ts
import { IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { GetCommentQuery } from '../impl';
import { Comment } from '../../models/comment.model';
@QueryHandler(GetCommentQuery)
export class GetCommentsHandler implements IQueryHandler<GetCommentQuery, Comment> {
async execute(query: GetCommentQuery) {
return new Comment('1');
}
}
handler/index.ts
import { GetCommentsHandler } from './get-comment.handler';
export const QueryHandlers = [GetCommentsHandler];
get-comment.query.ts
export class GetCommentQuery {}
impl/index.ts
export { GetCommentQuery } from './get-comment.query';
comments.controller.ts
import { Controller, Get } from '@nestjs/common';
import { QueryBus } from '@nestjs/cqrs';
import { Comment } from './models/comment.model';
import { GetCommentQuery } from './queries/impl';
@Controller('comments')
export class CommentsController {
constructor(
private readonly queryBus: QueryBus,
) {}
@Get()
async findAll(): Promise<Comment> {
return this.queryBus.execute(new GetCommentQuery());
}
}
comments.module.ts
import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { CommentsController } from './comments.controller';
import { QueryHandlers } from './queries/handlers';
@Module({
imports: [CqrsModule],
controllers: [CommentsController],
providers: [
...QueryHandlers,
],
})
export class CommentsModule {}
用示例图说明如下
Controller与Service之间加入了Mediator(ServiceBus)作为中间人。 在NestJS中,这个中间层通过标签injectable标记的Query类型,代码如下
@QueryHandler(GetCommentQuery)
this.queryBus.execute(new GetCommentQuery());
来寻找对应的Query Handler。
至此,Query的部分说完了,Command的部分会在下一篇文章中再做解释。