nestjs 架构篇:控制器、服务、数据访问
核心架构分层
控制器层
职责:处理 HTTP 请求/响应,参数校验,路由分发
设计原则:
仅关注 HTTP 协议交互
无业务逻辑,仅调用服务层
使用装饰器定义路由和参数映射
代码示例:
// user.controller.ts
@Controller('users')
export class UserController {constructor(private readonly userService: UserService) {}@Post()async create(@Body() createUserDto: CreateUserDto) {return this.userService.create(createUserDto);}@Get(':id')findOne(@Param('id', ParseIntPipe) id: number) {return this.userService.findOne(id);}
}关键点:
@Body()自动解析请求体@Param()提取路由参数依赖注入
UserService
服务层
职责:实现核心业务逻辑,协调数据访问
设计原则:
保持无状态(Stateless)
依赖注入数据访问层
使用 DTO 进行数据转换
代码示例:
// user.service.ts
@Injectable()
export class UserService {constructor(@InjectRepository(User)private readonly userRepository: Repository<User>) {}async create(userDto: CreateUserDto): Promise<User> {const user = this.userRepository.create(userDto);return this.userRepository.save(user);}async findOne(id: number): Promise<User> {return this.userRepository.findOneBy({ id });}
}关键点:
使用 TypeORM Repository 进行数据库操作
业务逻辑与数据持久化解耦
数据访问层
职责:数据库交互,数据持久化
实现方式:
Repository 模式:通过 TypeORM/Prisma 实现
DAO 模式:直接使用数据库驱动
代码示例(TypeORM):
// user.entity.ts
@Entity()
export class User {@PrimaryGeneratedColumn()id: number;@Column({ unique: true })email: string;@CreateDateColumn()createdAt: Date;
}// database.module.ts
@Module({imports: [TypeOrmModule.forRoot({type: 'postgres',host: 'localhost',port: 5432,entities: [User],synchronize: true})]
})
export class DatabaseModule {}关键点:
实体类定义数据库表结构
模块化配置数据库连接
模块化架构设计
模块定义规范
// user.module.ts
@Module({imports: [DatabaseModule],controllers: [UserController],providers: [UserService],exports: [UserService] // 暴露给其他模块
})
export class UserModule {}核心要素:
imports:依赖的其他模块exports:导出可复用的组件默认单例作用域
模块间通信
// auth.module.ts
@Module({imports: [forwardRef(() => UserModule)] // 解决循环依赖
})
export class AuthModule {}最佳实践:
按业务领域划分模块(如用户、订单、支付)
通过
exports控制服务暴露范围使用
forwardRef()处理循环依赖
依赖注入系统
依赖注入机制
// 服务注入示例
@Controller('orders')
export class OrderController {constructor(private readonly orderService: OrderService,@Inject('PAYMENT_SERVICE') private paymentService: PaymentService) {}
}实现原理:
@Injectable()标记可注入类容器自动解析构造函数参数类型
支持类/值/工厂三种提供者类型
高级注入场景
异步配置注入:
@Module({providers: [{provide: 'CONFIG_OPTIONS',useFactory: async () => loadConfig()}]
})
export class ConfigModule {}循环依赖解决方案:
@Module({imports: [forwardRef(() => BModule)]
})
export class AModule {}关键点:
优先使用构造函数注入
避免属性注入的隐式依赖
异常处理与数据校验
全局异常过滤器
// exceptions.filter.ts
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {catch(exception: unknown, host: ArgumentsHost) {const ctx = host.switchToHttp();const response = ctx.getResponse();response.status(500).json({ error: 'Internal Server Error' });}
}// main.ts 注册全局过滤器
app.useGlobalFilters(new AllExceptionsFilter());数据校验管道
// user.dto.ts
export class CreateUserDto {@IsEmail()email: string;@MinLength(6)password: string;
}// 控制器中使用
@Post()
async create(@Body() createUserDto: CreateUserDto) {// 自动触发校验
}关键点:
结合 class-validator 实现运行时校验
支持自定义校验器
最佳实践总结
分层架构
严格区分 Controller/Service/Repository 层
服务层保持无状态,数据访问层封装数据库操作
模块化设计
按业务领域划分模块
通过
exports控制服务暴露范围使用动态模块实现配置化
依赖注入
优先使用构造函数注入
合理使用作用域(Singleton/Request)
数据持久化
使用 TypeORM/Prisma 实现 Repository 模式
实体类与数据库表结构严格映射
异常处理
全局异常过滤器统一处理错误
自定义异常类增强错误语义
