Java码农快转Node:nest.js框架从入门到精通
2025-01-15 09:18 阅读(112)

1. NestJS 简介

NestJS 由 Kamil Mysliwiec 于 2016 年创立,是一个开源的 Node.js 后端框架。它结合了面向对象编程(OOP)、函数式编程(FP)和函数响应式编程(FRP)的思想,并且内置对 TypeScript 的支持,提供了高度的可扩展性与可维护性。


受 Angular 启发:NestJS 的设计理念与 Angular 类似,使用依赖注入(Dependency Injection)与模块化概念,简化了复杂业务逻辑的拆分和组合。

基于 Express(或 Fastify) :默认使用 Express.js 作为 HTTP 服务器,但也可以轻松切换到性能更佳的 Fastify。

易于上手:拥有活跃的社区和完善的文档,对于新手和资深开发者都非常友好。


如果你之前的技术栈是Springboot 或者 Springcloud,你会比较容易接受nest.js框架的编码模式。


2. 创建基础项目

2.1 安装 Nest CLI

如果你想快速创建一个新的 NestJS 项目并进行开发,官方推荐使用 Nest CLI 工具。可执行以下命令安装:

npm i -g @nestjs/cli

2.2 创建新项目

安装完 CLI 之后,可以使用如下命令快速创建并启动一个新项目:

nest new my-nest-project
cd my-nest-project
npm run start

执行 npm run start 后,你就可以在浏览器中访问 http://localhost:3000,测试基本的「Hello World」接口。


3. 核心概念快速回顾


模块(Module) :用于组织和管理控制器(Controller)、服务(Provider/Service)、以及其他组件。每个模块可以看作是一个业务功能或领域的集合。

控制器(Controller) :负责处理路由请求和响应,类似于 MVC 架构中的“C”。

提供者(Provider/Service) :主要用于编写业务逻辑,可被控制器或其他服务注入(DI)使用。

依赖注入(DI) :通过在构造函数参数中声明需要的依赖(服务),NestJS 会自动实例化并注入。



4. 基础 GET 请求示例

以下示例展示了一个最简单的 GET 请求处理方式,返回「Hello World」字符串。

import { Controller, Get } from '@nestjs/common';

@Controller('hello')
export class HelloController {
  @Get()
  getHello(): string {
    return 'Hello World!';
  }
}

@Controller('hello'):将该控制器的访问路径定义为 /hello。

@Get():声明此方法处理对 /hello 路径的 GET 请求。

getHello():返回一个字符串,可以在浏览器或工具(如 Postman)中通过 GET /hello 查看。


4.1 补充:在服务中处理逻辑

一般情况下,我们会将业务逻辑放到服务(Service)里,以便更好的维护和测试。示例:

// hello.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class HelloService {
  getHelloMessage(): string {
    return 'Hello World from Service!';
  }
}
// hello.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HelloService } from './hello.service';

@Controller('hello')
export class HelloController {
  constructor(private readonly helloService: HelloService) {}

  @Get()
  getHello(): string {
    return this.helloService.getHelloMessage();
  }
}

HelloService 通过 @Injectable() 装饰器表明它可以被依赖注入。

在 HelloController 的构造函数中通过 private readonly helloService: HelloService 注入服务实例。

这样可以更加清晰地划分控制器(处理请求)和服务(处理业务逻辑)的责任。



5. 基础 POST 请求示例

下面我们展示如何处理一个最简单的 POST 请求,并获取请求体中的数据。

import { Controller, Post, Body } from '@nestjs/common';

class CreateMessageDto {
  content: string;
  submittedBy: string;
}

@Controller('messages')
export class MessagesController {
  @Post()
  createMessage(@Body() message: CreateMessageDto): CreateMessageDto {
    console.log('收到的数据:', message);
    // 实际场景中,你可能会将这个信息写入数据库,或做其他业务处理
    return message; // 简单地把消息再原样返回
  }
}

@Controller('messages'):将控制器路径设为 /messages。

@Post():声明此方法处理对 /messages 的 POST 请求。

@Body():装饰器从请求体中提取 JSON 数据,并自动转换为 CreateMessageDto 的实例。


5.1 补充:结合服务和数据库

在真实项目中,你可能需要将数据写入数据库。以下是简单示例:

// messages.service.ts
import { Injectable } from '@nestjs/common';

interface Message {
  content: string;
  submittedBy: string;
  id: number;
}

@Injectable()
export class MessagesService {
  private messages: Message[] = [];
  private idCounter = 1;

  create(message: Omit<Message, 'id'>): Message {
    const newMessage: Message = { ...message, id: this.idCounter++ };
    this.messages.push(newMessage);
    return newMessage;
  }

  findAll(): Message[] {
    return this.messages;
  }
}
// messages.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { MessagesService } from './messages.service';

interface CreateMessageDto {
  content: string;
  submittedBy: string;
}

@Controller('messages')
export class MessagesController {
  constructor(private readonly messagesService: MessagesService) {}

  @Post()
  create(@Body() messageDto: CreateMessageDto) {
    return this.messagesService.create(messageDto);
  }

  @Get()
  findAll() {
    return this.messagesService.findAll();
  }
}

MessagesService 中维护了一个内存数组 messages,并提供 create 和 findAll 方法来操作数据。

MessagesController 中注入 MessagesService,通过 create 方法处理 POST 请求,通过 findAll 方法处理 GET 请求。


这样就完成了一个非常简易的「消息」管理功能:


POST /messages:创建消息

GET /messages:查看所有消息



6. 补充更多常见场景示例

6.1 获取路径参数和查询参数

在大多数业务中,除了请求体外,还会常用到“路径参数(Path Parameters)”和“查询参数(Query Parameters)”。

import { Controller, Get, Param, Query } from '@nestjs/common';

@Controller('users')
export class UsersController {
  // GET /users/123
  @Get(':id')
  findOne(@Param('id') id: string) {
    return `用户的 ID 为:${id}`;
  }

  // GET /users/search?keyword=Nest
  @Get('search')
  search(@Query('keyword') keyword: string) {
    return `搜索关键字为:${keyword}`;
  }
}

@Param('id'):获取路由定义中的 :id 部分的值。

@Query('keyword'):获取查询参数 keyword 的值。


6.2 PUT 和 DELETE 示例

在 RESTful API 中,常常需要更新或删除数据,可使用 @Put() 和 @Delete() 装饰器。

import { Controller, Put, Delete, Param } from '@nestjs/common';

@Controller('articles')
export class ArticlesController {
  // PUT /articles/10
  @Put(':id')
  updateArticle(@Param('id') id: string): string {
    // 这里你可能会根据 id 更新数据库中的文章
    return `更新了文章,ID 为:${id}`;
  }

  // DELETE /articles/10
  @Delete(':id')
  deleteArticle(@Param('id') id: string): string {
    // 这里你可能会根据 id 删除对应的文章
    return `删除了文章,ID 为:${id}`;
  }
}

7. 结语

通过上述示例,我们展示了在 NestJS 中实现常见的 GET、POST、PUT、DELETE 请求的基本方式,以及如何获取路径参数和查询参数。若要将这些示例投入实际生产项目,通常还需要结合以下内容:

https://www.zuocode.com

数据库集成:如使用 TypeORM、Prisma 等ORM框架操作数据库。

验证与管道(Validation & Pipes) :如使用 class-validator 和 class-transformer 对请求数据进行验证。

中间件和拦截器(Middleware & Interceptors) :如日志记录、异常处理、认证和授权(JWT/Passport)等。

微服务(Microservices) :NestJS 也提供了内置的微服务支持,可以更好地处理分布式应用场景。


NestJS 提供了清晰的结构和强大的依赖注入机制,使得项目的可维护性和可扩展性大大提高。


作者:Y11_推特同名

链接:https://juejin.cn