Nest 基础概念
Nest.js 是一个 Node.js 的后端框架,类似于 Java 的 Spring。它提供了完整的应用架构,帮助我们更好地组织代码结构。
1. 请求处理流程
Controller(控制器)
Controller 负责处理传入的请求和向客户端返回响应:
@Controller("user")
export class UserController {
@Get("list") // GET /user/list
getUsers() {
return ["小明", "小红"];
}
@Post("create") // POST /user/create
createUser() {
return "创建成功";
}
}
请求参数装饰器
- @Params - 路径参数
@Get(':userId')
getUser(@Param('userId') userId: string) {
return userId; // GET /user/123
}
- @Query - 查询参数
@Get('search')
searchUsers(@Query('name') name: string, @Query('age') age: number) {
return `查询:${name}, ${age}`; // GET /user/search?name=小明&age=18
}
- @Body - 请求体
@Post()
createUser(@Body() user: CreateUserDto) {
return { success: true, data: user }; // POST /user body: {...}
}
DTO(数据传输对象)
DTO 作为请求数据的验证层:
export class CreateUserDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
@IsNumber()
@Min(0)
age: number;
@IsEnum(["admin", "user"])
role: "admin" | "user";
}
Entity(实体)
Entity 用于映射数据库表结构:
// user.entity.ts
@Entity("users")
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@Column()
age: number;
@Column({
type: "enum",
enum: ["admin", "user"],
default: "user",
})
role: string;
@Column({ select: false }) // 查询时默认不返回密码字段
password: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
// 关联关系
@OneToMany(() => Post, (post) => post.author)
posts: Post[];
@ManyToMany(() => Role)
@JoinTable()
roles: Role[];
}
Entity 与 DTO 的区别:
Entity
- 映射数据库表结构
- 使用 TypeORM 装饰器(@Entity, @Column 等)
- 包含完整的数据库字段(id, 创建时间等)
- 可以定义表关系(一对多,多对多等)
- 通常与整个应用生命周期相关
DTO
- 用于请求数据的验证和传输
- 使用验证装饰器(@IsString, @IsEmail 等)
- 只包含请求需要的字段
- 不包含敏感信息(如密码)
- 通常与具体请求相关(CreateUserDto, UpdateUserDto)
2. 依赖注入(DI)
Service 注入
Service 封装业务逻辑,通过依赖注入的方式与 Controller 协作:
@Injectable()
export class UserService {
async createUser(user: CreateUserDto) {
// 业务逻辑
return { id: 1, ...user };
}
}
@Controller("user")
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
createUser(@Body() user: CreateUserDto) {
return this.userService.createUser(user);
}
}
Provider 类型
@Module({
providers: [
UserService, // 标准写法
{
provide: 'APP_SERVICE', // useClass
useClass: AppService
},
{
provide: 'CONFIG', // useValue
useValue: { apiUrl: '...' }
},
{
provide: 'ASYNC_SERVICE', // useFactory
useFactory: async () => {
const config = await loadConfig();
return new Service(config);
}
}
]
})
注入方式
- 构造器注入
@Controller("user")
export class UserController {
// 标准 Service 可以直接注入
constructor(
private readonly userService: UserService,
private readonly authService: AuthService,
// 自定义 provider 需要用 @Inject
@Inject("CONFIG") private readonly config: AppConfig,
@Inject("DATABASE") private readonly db: Database
) {}
}
- 属性注入
@Controller("user")
export class UserController {
@Inject(UserService)
private readonly userService: UserService;
@Inject("CONFIG")
private readonly config: AppConfig;
}
3. 项目结构
标准的模块结构:
src/
├── user/
│ ├── dto/
│ │ └── create-user.dto.ts
│ ├── entities/
│ │ └── user.entity.ts
│ ├── user.controller.ts
│ ├── user.service.ts
│ └── user.module.ts
├── app.module.ts
└── main.ts
4. MVC 架构
controller 是处理路由,解析请求参数的。
service 是处理业务逻辑的,比如操作数据库。
dto 是封装请求参数的。
entities 是封装对应数据库表的实体的。
nest 应用跑起来后,会从 AppModule 开始解析,初始化 IoC 容器,加载所有的 service 到容器里,然后解析 controller 里的路由,接下来就可以接收请求了。
MVC 是一种软件架构模式,它将应用程序分为三个主要部分:
Model(模型)
- Service: 处理业务逻辑
- Repository: 负责数据访问
- Entity: 数据库实体定义
View(视图)
- 在 Nest 中通常是 JSON 响应
- 也可以是模板引擎渲染的 HTML
- 或者其他格式的响应数据
Controller(控制器)
- 处理 HTTP 请求
- 参数验证和转换
- 调用相应的 Service
- 返回处理结果
这种分层架构的好处:
- 关注点分离
- 代码复用
- 便于维护和测试
- 提高代码的可读性和可维护性
5. AOP 架构
Nest 提供了 5 种切面:
- Middleware: 中间件
- Guard: 守卫
- Interceptor: 拦截器
- Pipe: 管道
- Exception Filter: 异常过滤器
总结
controller:控制器,用于处理路由,解析请求参数
handler:控制器里处理路由的方法
service:实现业务逻辑的地方,比如操作数据库等
dto:data transfer object,数据传输对象,用于封装请求体里数据的对象
module:模块,包含 controller、service 等,比如用户模块、书籍模块
entity:对应数据库表的实体
ioc:Inverse of Controller,反转控制或者叫依赖注入,只要声明依赖,运行时 Nest 会自动注入依赖的实例
aop:Aspect Oriented Programming 面向切面编程,在多个请求响应流程中可以复用的逻辑,比如日志记录等,具体包含 middleware、interceotor、guard、exception filter、pipe