前端转型全栈(二)——NestJS 入门指南:从 Angular 开发者视角理解后端架构

作为一名前端开发者,当第一次接触 NestJS 时,一种强烈的熟悉感扑面而来------这目录结构、这装饰器语法、这模块化设计,不就是 Angular 吗?

事实上,这种相似性绝非巧合。本文将从两个维度带你深入理解 NestJS:

  1. 架构渊源:为什么 NestJS 和 Angular 如此相似?

  2. 实战基础:掌握 NestJS 中的各种 HTTP 请求处理方式

一、NestJS 与 Angular 的渊源

1.1 创始人背景

NestJS 由 Kamil Myśliwiec 于 2017 年创建,他是一位 Google Developer Expert。在官方文档中,他毫不讳言:

"The architecture is heavily inspired by Angular."

(NestJS 的架构深受 Angular 启发)

Kamil 创建 NestJS 的初衷是解决 Node.js 后端缺乏统一架构的问题。当时前端已有 Angular、React、Vue 等成熟框架,但后端 Node.js 生态中虽然库很多(如 Express),却没有提供开箱即用的应用架构。

1.2 架构对比

|--------|-----------------------|---------------|
| 概念 | Angular(前端) | NestJS(后端) |
| 模块化 | @NgModule() | @Module() |
| 依赖注入 | @Injectable() | @Injectable() |
| 控制器/组件 | @Component() | @Controller() |
| 服务层 | *.service.ts | *.service.ts |
| cli工具 | ng generate | nest generate |
| DTO/接口 | TypeScript Interfaces | DTO Classes |

1.3 全栈开发的优势

这种相似性带来了真实的开发优势:

  1. 心智模型统一:前端用 Angular,后端用 NestJS,团队可以在两种环境间无缝切换

  2. 代码共享:通过 Nx monorepo 可以共享 TypeScript 接口、DTO、验证逻辑

  3. 学习成本低:熟悉 Angular 的开发者可以在几天内上手 NestJS

这也是为什么现代全栈开发中经常出现 "A2N 技术栈"(Angular + NestJS + Nx)的组合。

二、NestJS HTTP 请求方式详解

下面通过一个完整的 CatsController 示例,详细讲解 NestJS 中各种请求方式的区别。

2.1 完整代码示例

复制代码
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';

@Controller('cats')
export class CatsController {
  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    return 'This action adds a new cat';
  }

  @Get()
  findAll(@Query() query: ListAllEntities) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return `This action returns a #${id} cat`;
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
    return `This action updates a #${id} cat`;
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return `This action removes a #${id} cat`;
  }
}

2.2 HTTP 方法与 CRUD 对应关系

|----------------|---------|------|---------------|------------------|-----|
| 装饰器 | HTTP 方法 | 语义 | 对应操作 | 示例路由 | 幂等性 |
| @Post() | POST | 创建资源 | Create | POST /cats | 非冥等 |
| @Get() | GET | 获取列表 | Read (列表) | GET /cats | 冥等 |
| @Get(':id') | GET | 获取单个 | Read (单条) | GET /cats/123 | 冥等 |
| @Put(':id') | PUT | 全量更新 | Update | PUT /cats/123 | 冥等 |
| @Delete(':id') | DELETE | 删除资源 | Delete | DELETE /cats/123 | 冥等 |

2.3 各方法详细解析

① @Post() - 创建资源
复制代码
@Post()
create(@Body() createCatDto: CreateCatDto) {
  return 'This action adds a new cat';
}
  • 特性:非幂等,多次调用会创建多个资源

  • 传参方式 :通过 @Body() 获取请求体中的 JSON 数据

② @Get() - 获取资源列表
复制代码
@Get()
findAll(@Query() query: ListAllEntities) {
  return `This action returns all cats (limit: ${query.limit} items)`;
}
  • 特性:幂等且安全,不修改服务器状态

  • 传参方式 :通过 @Query() 获取 URL 查询参数(如 ?limit=10&page=1

③ @Get(':id') - 获取单个资源
复制代码
@Get(':id')
findOne(@Param('id') id: string) {
  return `This action returns a #${id} cat`;
}
④ @Put(':id') - 全量更新
复制代码
@Put(':id')
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
  return `This action updates a #${id} cat`;
}
  • 特性:幂等,多次相同请求结果一致

  • 重要区别 :PUT 是全量更新,客户端必须提供资源的全部字段

  • 对比 PATCH:PATCH 是部分更新,只需发送要修改的字段

PUT vs PATCH 示例

复制代码
// PUT 请求:{ age: 3 } → 资源变成只有 age 字段,其他被清空
// PATCH 请求:{ age: 3 } → 只更新 age,其他字段保持不变
⑤ @Delete(':id') - 删除资源
复制代码
@Delete(':id')
remove(@Param('id') id: string) {
  return `This action removes a #${id} cat`;
}
  • 特性:幂等,删除一次和多次结果相同(资源不存在后再次删除仍是"不存在"状态)

  • 请求示例

    curl -X DELETE http://localhost:3000/cats/123

2.4 参数装饰器对比

|--------------|--------------------|----------------------|----------------------|---|
| 装饰器 | 数据来源 | 用途 | 示例 | |
| @Body() | 请求体 (Request Body) | POST/PUT 的表单/JSON 数据 | { "name": "Tom" } | |
| @Query() | URL 查询参数 | 过滤、分页、搜索 | ?limit=10&page=1 | |
| @Param('id') | URL 路径参数 | 资源标识 | /cats/123 中的 123 | |

三、完整请求示例汇总

复制代码
# 1. 创建(Create)
curl -X POST http://localhost:3000/cats \
  -H "Content-Type: application/json" \
  -d '{"name":"Tom","age":2,"breed":"Persian"}'

# 2. 列表查询(Read All)
curl "http://localhost:3000/cats?limit=10"

# 3. 单条查询(Read One)
curl http://localhost:3000/cats/123

# 4. 更新(Update)
curl -X PUT http://localhost:3000/cats/123 \
  -H "Content-Type: application/json" \
  -d '{"name":"Tom","age":3,"breed":"Persian"}'

# 5. 删除(Delete)
curl -X DELETE http://localhost:3000/cats/123

四、总结

NestJS 的设计哲学

  1. 统一架构:借鉴 Angular 的模块化、依赖注入等成熟设计

  2. TypeScript 优先:提供完整的类型支持

  3. RESTful 规范:通过装饰器实现语义化的 API 设计

  4. 全栈友好:让前端开发者(尤其是 Angular 用户)能快速上手后端开发

相关推荐
恋猫de小郭2 小时前
AGP 9.2 开始,Android 上协程启动和取消速度提升两倍
android·前端·flutter
Ulyanov2 小时前
Python与YAML的优雅交响:从配置管理到数据艺术的完美实践 (一)
开发语言·前端·python·数据可视化
SuperEugene2 小时前
Python 函数与模块化:前端工程化思维完全通用| 基础篇
前端·python·状态模式
萧行之3 小时前
Ubuntu Node.js 版本管理工具 n 完整安装与使用教程
linux·前端
IT 行者9 小时前
Web逆向工程AI工具:JSHook MCP,80+专业工具让Claude变JS逆向大师
开发语言·javascript·ecmascript·逆向
devlei9 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
程序员 沐阳10 小时前
JavaScript 内存与引用:深究深浅拷贝、垃圾回收与 WeakMap/WeakSet
开发语言·javascript·ecmascript
Jagger_11 小时前
周末和AI肝了两天,终于知道:为什么要把AI当做实习生
前端