从 Spring Boot 到 NestJS项目快速上手指南本文档专为具有 Spring Boot 开发经验的开发者编写旨在通过类比和循序渐进的实战指导帮助你快速熟悉并参与到当前 NestJS 项目的开发中。第一阶段全局宏观认知1. 架构思想的无缝平移NestJS 几乎完美复刻了 Spring Boot 的架构哲学IoC/DI (控制反转与依赖注入)默认单例通过构造函数注入。AOP (面向切面编程)拦截器、守卫、异常过滤器一应俱全。模块化 (Module)按业务划分模块避免代码耦合。2. 核心装饰器注解对照表Spring BootNestJS作用说明RestControllerController()标记控制器定义路由前缀Service/ComponentInjectable()标记为 Provider交由 IoC 容器管理Autowired(无需显式注解)直接在类的constructor中声明即可自动注入GetMapping(/path)Get(path)GET 请求路由映射PostMappingPost()POST 请求路由映射RequestBodyBody()获取请求体 JSON 数据RequestParamQuery()获取 URL 查询参数 (?keyvalue)PathVariableParam()获取路径参数 (/api/:id)第二阶段熟悉项目目录结构当前项目的结构与标准的 MVC 分层高度一致src/ ├── main.ts # 等同于 Application.java项目启动入口 ├── app.module.ts # 根模块等同于 SpringBootApplication 全局配置 ├── config/ # 配置文件目录等同于 application.yml ├── common/ # 通用工具类、拦截器、全局异常处理等 │ ├── base/ # 基础 Controller/Service 类可继承复用 │ ├── decorators/ # 自定义装饰器自定义注解 │ ├── interceptors/ # 拦截器如统一返回值包装 transform.interceptor.ts │ └── filters/ # 异常过滤器全局异常捕获 ├── module/ # 业务模块目录 │ ├── ota/ # OTA核心业务模块 │ │ ├── xxx.controller.ts # 控制层 │ │ ├── xxx.service.ts # 业务逻辑层 │ │ ├── xxx.entity.ts # 数据库实体类 (等同于 Entity) │ │ ├── xxx.module.ts # 模块组装文件 (必须将Controller和Service注册在此) │ │ └── dto/ # 数据传输对象 (入参/出参校验)第三阶段ORM 与数据库操作 (TypeORM)本项目使用TypeORM体验上非常接近JPA和Hibernate。1. 实体定义 (Entity)类似 JPA通过装饰器映射表结构import{Entity,Column,PrimaryGeneratedColumn}fromtypeorm;Entity(sys_user)// Table(name sys_user)exportclassUser{PrimaryGeneratedColumn()// Id GeneratedValueid:number;Column({name:user_name,length:50})// ColumnuserName:string;}2. 数据库操作 (Repository)类似于JpaRepository在 Service 中注入Repository即可进行 CRUDimport{Injectable}fromnestjs/common;import{InjectRepository}fromnestjs/typeorm;import{Repository}fromtypeorm;import{User}from./user.entity;Injectable()exportclassUserService{// 等同于 Autowired private UserRepository userRepository;constructor(InjectRepository(User)privatereadonlyuserRepository:RepositoryUser,){}asyncfindUser(id:number){returnawaitthis.userRepository.findOne({where:{id}});}}第四阶段实战演练手把手写一个接口假设我们需要在src/module/ota/下新建一个获取航班列表的接口。请遵循单一职责和最小开发单元的规则。Step 1: 定义入参 DTO (flight-query.dto.ts)等同于 Java 的 Request 对象。使用class-validator进行校验类似Validjavax.validation。import{IsString,IsNotEmpty}fromclass-validator;exportclassFlightQueryDto{IsString()IsNotEmpty({message:出发地不能为空})depCity:string;IsString()IsNotEmpty({message:目的地不能为空})arrCity:string;}Step 2: 编写 Service (flight.service.ts)实现核心业务逻辑。注意优先使用卫语句early return复杂逻辑请拆分。import{Injectable}fromnestjs/common;import{FlightQueryDto}from./dto/flight-query.dto;import{ObjectUtils}fromsrc/common/utils/object.util;// 假设有这个工具类Injectable()exportclassFlightService{asyncgetFlightList(query:FlightQueryDto){// 卫语句优先拦截异常情况if(ObjectUtils.isEmpty(query.depCity)||ObjectUtils.isEmpty(query.arrCity)){thrownewError(城市参数缺失);// 全局 Filter 会捕获并格式化抛出}// 业务逻辑处理...return[{flightNo:CZ3201,dep:query.depCity,arr:query.arrCity}];}}Step 3: 编写 Controller (flight.controller.ts)接收请求调用 Service。import{Controller,Get,Query}fromnestjs/common;import{FlightService}from./flight.service;import{FlightQueryDto}from./dto/flight-query.dto;Controller(ota/flight)// 相当于 RequestMapping(/ota/flight)exportclassFlightController{// 构造函数注入 Serviceconstructor(privatereadonlyflightService:FlightService){}Get(list)// 相当于 GetMapping(/list)asyncgetList(Query()query:FlightQueryDto){returnawaitthis.flightService.getFlightList(query);}}Step 4: 在 Module 中注册⚠️最容易忘的一步必须将新建的 Controller 和 Service 注册到对应的 Module 中否则 IoC 容器无法识别。import{Module}fromnestjs/common;import{FlightController}from./flight.controller;import{FlightService}from./flight.service;Module({controllers:[FlightController],providers:[FlightService],// 相当于放入 Spring 容器exports:[FlightService],// 如果其他模块需要用 FlightService必须导出})exportclassFlightModule{}第五阶段团队编码规范与避坑指南结合本项目的规范要求在编码时请严格遵守以下几点异步处理 (Async/Await)Node.js 是单线程的所有涉及 I/O查库、HTTP请求、读写文件的方法都必须返回Promise并在调用时使用await。导入规范使用import { xxx } from ...的方式导入将相似的导入放在类的最上面严禁在类中直接使用xx.xxx.xxx方式引用。判空规范优先使用ObjectUtils.isEmpty()进行非空判断而不是直接使用 null。异常处理除了打印日志必须抛出异常不要吞掉异常以便被全局异常过滤器处理。代码整洁度优先使用卫语句 (Guard Clause / early return)减少嵌套。单个方法内保证有效代码在15行内。复杂问题拆解为更小模块复杂的校验逻辑应从 Service 抽离到独立的 Validator 类中。当有常量时优先抽出来作为常量进行调用。面向对象与可维护性按最小开发单元生成代码每个类功能要单一。避免重复代码建议使用继承、多态等机制复用。避免出现内部类。性能规范考虑代码执行效率如不要循环插入数据库应使用批量插入。并发与状态一致性高并发场景下倾向使用“Redis分布式锁 数据库唯一索引 条件更新CAS”组合方案。