返回博客

NestJS 企业级应用开发实战

使用 NestJS 构建可扩展、可维护的企业级后端应用,涵盖架构设计、模块化、数据库集成等。

NestJS 企业级应用开发实战
4 天前
8 分钟阅读
421 次浏览

NestJS 企业级应用开发实战

NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用的框架。它使用渐进式 JavaScript,完全支持 TypeScript。

为什么选择 NestJS?

  1. TypeScript 优先:完整的类型安全
  2. 模块化架构:易于组织和维护
  3. 依赖注入:松耦合、易测试
  4. 开箱即用:集成常用功能
  5. 企业级架构:适合大型项目

项目结构

text
src/ ├── app.module.ts ├── main.ts ├── common/ # 公共模块 │ ├── filters/ │ ├── guards/ │ ├── interceptors/ │ └── pipes/ ├── config/ # 配置 │ └── database.config.ts ├── modules/ │ ├── users/ │ │ ├── users.controller.ts │ │ ├── users.service.ts │ │ ├── users.module.ts │ │ ├── dto/ │ │ └── entities/ │ └── posts/ └── shared/ # 共享资源

基础模块

Controller

typescript
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation } from '@nestjs/swagger'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; @ApiTags('posts') @Controller('posts') export class PostsController { constructor(private readonly postsService: PostsService) {} @Get() @ApiOperation({ summary: '获取所有文章' }) findAll() { return this.postsService.findAll(); } @Post() @UseGuards(JwtAuthGuard) @ApiOperation({ summary: '创建文章' }) create(@Body() createPostDto: CreatePostDto) { return this.postsService.create(createPostDto); } @Get(':id') findOne(@Param('id') id: string) { return this.postsService.findOne(id); } }

Service

typescript
import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; @Injectable() export class PostsService { constructor( @InjectRepository(Post) private postsRepository: Repository<Post>, ) {} async findAll(): Promise<Post[]> { return this.postsRepository.find({ relations: ['author', 'tags'], }); } async findOne(id: string): Promise<Post> { const post = await this.postsRepository.findOne({ where: { id }, relations: ['author', 'tags'], }); if (!post) { throw new NotFoundException(`Post with ID ${id} not found`); } return post; } async create(createPostDto: CreatePostDto): Promise<Post> { const post = this.postsRepository.create(createPostDto); return this.postsRepository.save(post); } }

Module

typescript
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { PostsController } from './posts.controller'; import { PostsService } from './posts.service'; import { Post } from './entities/post.entity'; @Module({ imports: [TypeOrmModule.forFeature([Post])], controllers: [PostsController], providers: [PostsService], exports: [PostsService], }) export class PostsModule {}

DTO 和验证

typescript
import { IsString, IsNotEmpty, MinLength, IsOptional } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class CreatePostDto { @ApiProperty({ description: '文章标题' }) @IsString() @IsNotEmpty() @MinLength(3) title: string; @ApiProperty({ description: '文章内容' }) @IsString() @IsNotEmpty() content: string; @ApiProperty({ description: '摘要', required: false }) @IsString() @IsOptional() excerpt?: string; }

数据库集成(TypeORM)

Entity

typescript
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, ManyToMany } from 'typeorm'; @Entity('posts') export class Post { @PrimaryGeneratedColumn('uuid') id: string; @Column() title: string; @Column('text') content: string; @Column({ nullable: true }) excerpt: string; @Column({ default: 0 }) viewCount: number; @ManyToOne(() => User, user => user.posts) author: User; @ManyToMany(() => Tag, tag => tag.posts) tags: Tag[]; @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) createdAt: Date; }

认证与授权

JWT 策略

typescript
import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: process.env.JWT_SECRET, }); } async validate(payload: any) { return { userId: payload.sub, email: payload.email, role: payload.role }; } }

Guards

typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler()); if (!requiredRoles) { return true; } const { user } = context.switchToHttp().getRequest(); return requiredRoles.some(role => user.role === role); } } // 使用 @Post() @Roles('admin') @UseGuards(JwtAuthGuard, RolesGuard) create(@Body() createPostDto: CreatePostDto) { return this.postsService.create(createPostDto); }

拦截器

typescript
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class TransformInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { return next.handle().pipe( map(data => ({ success: true, data, timestamp: new Date().toISOString(), })), ); } }

异常过滤器

typescript
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 request = ctx.getRequest(); const status = exception.getStatus(); response.status(status).json({ success: false, statusCode: status, timestamp: new Date().toISOString(), path: request.url, message: exception.message, }); } }

配置管理

typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: `.env.${process.env.NODE_ENV}`, }), ], }) export class AppModule {}

测试

单元测试

typescript
describe('PostsService', () => { let service: PostsService; let repository: Repository<Post>; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [ PostsService, { provide: getRepositoryToken(Post), useValue: { find: jest.fn(), findOne: jest.fn(), create: jest.fn(), save: jest.fn(), }, }, ], }).compile(); service = module.get<PostsService>(PostsService); repository = module.get<Repository<Post>>(getRepositoryToken(Post)); }); it('should be defined', () => { expect(service).toBeDefined(); }); });

最佳实践

  1. 使用 DTO 验证输入
  2. 合理使用依赖注入
  3. 模块化设计
  4. 编写测试
  5. 使用环境变量
  6. 日志记录
  7. API 文档(Swagger)
  8. 错误处理

总结

NestJS 提供了构建企业级应用所需的一切:

  • 强大的架构模式
  • 完整的 TypeScript 支持
  • 丰富的生态系统
  • 易于测试和维护

标签:NestJS, Node.js, TypeScript

周温

周温

全栈开发工程师,专注于前端技术栈和物联网应用开发。拥有丰富的 React、Next.js、Nest.js 项目经验,擅长构建高性能、可扩展的 Web 应用。

评论 (0)

请先登录后再发表评论

登录

还没有评论,来发表第一条吧!