NestJS 企业级框架
NestJS 是基于 TypeScript 的 Node.js 框架,借鉴 Angular 的模块化架构,适合构建可维护的企业级后端。
核心架构
NestJS 架构(MVC + 依赖注入):
Request → Middleware → Guard → Interceptor → Pipe → Controller → Service → Repository
↓
Response ← Interceptor ← ExceptionFilter ←────────────────────────────── Database快速开始
bash
npm install -g @nestjs/cli
nest new my-api
cd my-api
# 生成资源(CRUD 模块)
nest generate resource users模块、控制器、服务
ts
// users/users.module.ts
import { Module } from '@nestjs/common'
import { TypeOrmModule } from '@nestjs/typeorm'
import { UsersController } from './users.controller'
import { UsersService } from './users.service'
import { User } from './entities/user.entity'
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService], // 允许其他模块使用
})
export class UsersModule {}
// users/users.controller.ts
import { Controller, Get, Post, Body, Param, Patch, Delete,
ParseIntPipe, UseGuards, HttpCode, HttpStatus } from '@nestjs/common'
import { UsersService } from './users.service'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'
@Controller('users')
@UseGuards(JwtAuthGuard) // 整个控制器需要认证
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto)
}
@Get()
findAll() {
return this.usersService.findAll()
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.usersService.findOne(id)
}
@Patch(':id')
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateUserDto: UpdateUserDto
) {
return this.usersService.update(id, updateUserDto)
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id', ParseIntPipe) id: number) {
return this.usersService.remove(id)
}
}
// users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { User } from './entities/user.entity'
import { CreateUserDto } from './dto/create-user.dto'
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>
) {}
async create(dto: CreateUserDto): Promise<User> {
const user = this.userRepository.create(dto)
return this.userRepository.save(user)
}
async findAll(): Promise<User[]> {
return this.userRepository.find()
}
async findOne(id: number): Promise<User> {
const user = await this.userRepository.findOne({ where: { id } })
if (!user) throw new NotFoundException(`用户 #${id} 不存在`)
return user
}
async update(id: number, dto: UpdateUserDto): Promise<User> {
const user = await this.findOne(id)
Object.assign(user, dto)
return this.userRepository.save(user)
}
async remove(id: number): Promise<void> {
const user = await this.findOne(id)
await this.userRepository.remove(user)
}
}DTO 与验证
ts
// users/dto/create-user.dto.ts
import { IsEmail, IsString, MinLength, IsEnum, IsOptional } from 'class-validator'
import { Transform } from 'class-transformer'
export class CreateUserDto {
@IsString()
@MinLength(2, { message: '姓名至少 2 个字符' })
name: string
@IsEmail({}, { message: '邮箱格式不正确' })
@Transform(({ value }) => value.toLowerCase())
email: string
@IsString()
@MinLength(8, { message: '密码至少 8 位' })
password: string
@IsEnum(['admin', 'user'])
@IsOptional()
role?: 'admin' | 'user' = 'user'
}
// 启用全局验证管道
// main.ts
import { ValidationPipe } from '@nestjs/common'
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // 自动剥离未声明的属性
forbidNonWhitelisted: true, // 有未知属性时报错
transform: true, // 自动类型转换
transformOptions: { enableImplicitConversion: true }
}))JWT 认证
ts
// auth/auth.module.ts
import { JwtModule } from '@nestjs/jwt'
import { PassportModule } from '@nestjs/passport'
@Module({
imports: [
PassportModule,
JwtModule.registerAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
secret: config.get('JWT_SECRET'),
signOptions: { expiresIn: '7d' }
})
}),
UsersModule
],
providers: [AuthService, JwtStrategy, LocalStrategy],
controllers: [AuthController],
})
export class AuthModule {}
// auth/strategies/jwt.strategy.ts
import { Injectable } from '@nestjs/common'
import { PassportStrategy } from '@nestjs/passport'
import { ExtractJwt, Strategy } from 'passport-jwt'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private config: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.get('JWT_SECRET')
})
}
async validate(payload: { sub: number; email: string }) {
return { id: payload.sub, email: payload.email }
// 返回值会挂载到 request.user
}
}
// auth/auth.service.ts
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService
) {}
async login(user: User) {
const payload = { sub: user.id, email: user.email }
return {
access_token: this.jwtService.sign(payload),
user: { id: user.id, name: user.name, email: user.email }
}
}
}拦截器与异常过滤器
ts
// 统一响应格式拦截器
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, ApiResponse<T>> {
intercept(context: ExecutionContext, next: CallHandler): Observable<ApiResponse<T>> {
return next.handle().pipe(
map(data => ({ code: 0, message: 'success', data }))
)
}
}
// 全局异常过滤器
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp()
const response = ctx.getResponse()
const status = exception.getStatus()
const exceptionResponse = exception.getResponse()
response.status(status).json({
code: status,
message: typeof exceptionResponse === 'string'
? exceptionResponse
: (exceptionResponse as any).message,
timestamp: new Date().toISOString()
})
}
}
// main.ts 注册全局
app.useGlobalInterceptors(new TransformInterceptor())
app.useGlobalFilters(new HttpExceptionFilter())总结
- NestJS 的模块化架构让大型项目易于维护和测试
- DTO + ValidationPipe 实现请求数据的自动验证和转换
- 依赖注入让服务解耦,便于单元测试(mock 依赖)
- 拦截器统一响应格式,异常过滤器统一错误处理
- 配合 Swagger(@nestjs/swagger)自动生成 API 文档