NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它完美地结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的元素。本文将带你从零开始了解 NestJS 的核心概念和基础用法。

环境准备与项目搭建

1. 环境准备

首先确保你的开发环境已经安装了 Node.js(推荐 v16 或更高版本)。然后全局安装 NestJS CLI:

npm i -g @nestjs/cli

2. 创建新项目

使用 CLI 创建新项目:

nest new my-nest-project
cd my-nest-project

选择包管理器(npm/yarn/pnpm)后,CLI 会自动创建项目结构并安装依赖。

3. 项目结构

src/
├── app.controller.spec.ts    # 控制器测试文件
├── app.controller.ts         # 基础控制器
├── app.module.ts            # 根模块
├── app.service.ts           # 基础服务
└── main.ts                  # 应用入口文件

核心概念

1. 控制器(Controllers)

控制器负责处理传来的请求和向客户端返回响应:

// src/app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';

@Controller('api')
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('hello')
  getHello(): string {
    return this.appService.getHello();
  }

  @Post('message')
  createMessage(@Body() message: { content: string }) {
    return this.appService.createMessage(message);
  }
}

2. 提供者(Providers)

提供者是 NestJS 中的基础概念,多数情况下用于封装业务逻辑:

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

@Injectable()
export class AppService {
  private messages: string[] = [];

  getHello(): string {
    return 'Hello World!';
  }

  createMessage(message: { content: string }): string {
    this.messages.push(message.content);
    return `Message created: ${message.content}`;
  }

  getAllMessages(): string[] {
    return this.messages;
  }
}

3. 模块(Modules)

模块是用来组织应用程序结构的基本单位:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

4. 中间件(Middleware)

中间件是在路由处理程序之前调用的函数:

// src/common/middleware/logger.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request... Method: ${req.method}, Path: ${req.path}`);
    next();
  }
}

// 在模块中应用中间件
// src/app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';

@Module({
  // ... 其他配置
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');
  }
}

5. 管道(Pipes)

管道用于数据转换和验证:

// src/common/pipes/validation.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';

@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(value: any, { metatype }: ArgumentMetadata) {
    if (!metatype || !this.toValidate(metatype)) {
      return value;
    }
    const object = plainToClass(metatype, value);
    const errors = await validate(object);
    if (errors.length > 0) {
      throw new BadRequestException('Validation failed');
    }
    return value;
  }

  private toValidate(metatype: Function): boolean {
    const types: Function[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}

6. 异常过滤器(Exception Filters)

用于处理应用程序中的异常:

// src/common/filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: exception.message,
      });
  }
}

7. 守卫(Guards)

守卫用于处理授权逻辑:

// src/common/guards/auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    // 在这里实现你的授权逻辑
    return true; // 或 false
  }
}

实战示例:创建一个简单的 REST API

让我们创建一个简单的用户管理 API:

// src/users/dto/create-user.dto.ts
import { IsString, IsEmail, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;

  @IsEmail()
  email: string;
}

// src/users/user.entity.ts
export class User {
  id: number;
  name: string;
  email: string;
}

// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './user.entity';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UsersService {
  private users: User[] = [];

  create(createUserDto: CreateUserDto): User {
    const user = {
      id: this.users.length + 1,
      ...createUserDto,
    };
    this.users.push(user);
    return user;
  }

  findAll(): User[] {
    return this.users;
  }

  findOne(id: number): User {
    return this.users.find(user => user.id === id);
  }
}

// src/users/users.controller.ts
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { AuthGuard } from '../common/guards/auth.guard';

@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

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

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }
}

// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

启动应用

main.ts 中配置和启动应用:

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // 全局管道
  app.useGlobalPipes(new ValidationPipe());
  
  // 全局过滤器
  app.useGlobalFilters(new HttpExceptionFilter());
  
  // 启动应用
  await app.listen(3000);
  console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

测试 API

使用 curl 或 Postman 测试 API:

# 创建用户
curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John Doe", "email": "john@example.com"}'

# 获取所有用户
curl http://localhost:3000/users

# 获取特定用户
curl http://localhost:3000/users/1

写在最后

本文介绍了 NestJS 的基础概念和核心功能:

  1. 项目搭建和结构
  2. 控制器和路由
  3. 提供者和服务
  4. 模块化组织
  5. 中间件和管道
  6. 异常处理
  7. 守卫和授权

这些概念构成了 NestJS 应用程序的基础。在下一篇文章中,我们将深入探讨 NestJS 的数据库操作和 TypeORM 集成。

如果觉得这篇文章对你有帮助,别忘了点个赞 👍


远洋录
3 声望0 粉丝

🚀 独立开发者 | 技术出海实践者