本文详细介绍了Nest框架的核心特点与优势,包括模块化结构、依赖注入、装饰器模式以及高性能等特性,帮助开发者更好地理解Nest后端开发。此外,文章还提供了安装与环境配置、快速搭建Nest项目、控制器与路由、服务与模块、数据库集成、跨域支持及环境变量配置等实用指南。
Nest框架是一个用于构建高效、可扩展的服务器端JavaScript应用程序的框架。它基于现代JavaScript(TypeScript)开发,使用了最新的ES2015+语言特性。Nest框架提供了模块化结构,允许开发者利用装饰器、依赖注入等特性,构建复杂的业务逻辑和API接口。
Nest框架的核心特点与优势包括:
安装Nest框架需要Node.js环境,建议使用Node.js版本14或更高版本。可以通过以下步骤安装Node.js和Nest CLI(命令行工具):
node -v
命令检查Node.js版本。安装Nest CLI可以通过npm(Node.js的包管理器)完成,执行以下命令:
npm i -g @nestjs/cli
此命令会全局安装Nest CLI工具,使其可以用于任何Nest项目中。
使用Nest CLI工具可以快速创建新的Nest项目。以下是创建Nest项目的步骤:
nest new <项目名称>
,例如创建一个名为 my-nest-app
的项目:
nest new my-nest-app
一个Nest项目的目录结构如下:
my-nest-app/ │ ├── src/ │ ├── app.module.ts │ ├── app.controller.ts │ ├── app.service.ts │ └── main.ts ├── node_modules/ ├── nest-cli.json ├── nest-cli.config.ts ├── package.json ├── tsconfig.json └── tsconfig.build.json
src/
:项目的源代码目录。app.module.ts
:项目的根模块。app.controller.ts
:项目的根控制器。app.service.ts
:项目的根服务。main.ts
:项目的入口文件。package.json
:项目的Node.js包配置文件。tsconfig.json
:TypeScript编译配置文件。tsconfig.build.json
:编译时使用的TypeScript配置文件。创建一个简单的Nest应用来显示 "Hello World"。
控制器用于处理HTTP请求。以下是在 src/app.controller.ts
文件中定义一个基本的控制器:
import { Controller, Get } from '@nestjs/common'; @Controller('hello') export class AppController { @Get() getHello(): string { return 'Hello World!'; } }
@Controller('hello')
:定义了一个路由前缀 hello
。@Get()
:定义了一个HTTP GET请求处理方法。getHello()
:返回一个字符串 "Hello World!"。在 src/app.module.ts
文件中引入控制器,并注册为应用模块的一部分:
import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; @Module({ imports: [], controllers: [AppController], providers: [], }) export class AppModule {}
在命令行中运行以下命令启动应用:
npm run start
启动后,默认监听8080端口,访问 http://localhost:3000/hello
可以看到 "Hello World!" 输出。
控制器用于处理HTTP请求。Nest框架中,控制器通过装饰器来定义路由和HTTP动词。以下是一个控制器的示例:
import { Controller } from '@nestjs/common'; @Controller('users') export class UsersController { // 更多方法... }
@Controller('users')
:定义一个路由前缀,所有该控制器中的方法都会加上这个前缀。控制器中的方法通过HTTP动词装饰器(如 @Get
、@Post
、@Put
、@Delete
)来定义路由和请求处理逻辑。例如:
import { Controller, Get, Post, Put, Delete } from '@nestjs/common'; @Controller('users') export class UsersController { @Get() getAllUsers(): string { return '获取所有用户'; } @Post() createUser(): string { return '创建用户'; } @Put(':id') updateUser(id: string): string { return `更新用户 ${id}`; } @Delete(':id') removeUser(id: string): string { return `删除用户 ${id}`; } }
@Get()
:处理GET请求。@Post()
:处理POST请求。@Put(':id')
:处理PUT请求,其中 :id
是路由参数。@Delete(':id')
:处理DELETE请求,其中 :id
是路由参数。路由参数通过在路由定义中使用:
来定义,例如 @Get(':id')
。在方法中可以使用参数解构来获取这些参数。例如:
import { Controller, Get, Param } from '@nestjs/common'; @Controller('users') export class UsersController { @Get(':id') getUser(@Param('id') id: string): string { return `获取用户 ${id}`; } }
@Param('id')
:从路由参数中解构出 id
参数。查询参数通过 @Query
装饰器来获取,例如 @Get('users')
请求中的查询参数。例如:
import { Controller, Get, Query } from '@nestjs/common'; @Controller('users') export class UsersController { @Get() getUsers(@Query('page') page: string): string { return `获取第 ${page} 页用户`; } }
@Query('page')
:从查询参数中解构出 page
参数。服务用于处理业务逻辑,通常将业务逻辑封装在服务中,然后通过依赖注入的方式供控制器使用。以下是如何创建一个服务的示例:
import { Injectable } from '@nestjs/common'; @Injectable() export class UserService { getUsers(): string { return '获取所有用户'; } }
@Injectable()
:标记该类为可注入的服务。服务可以通过构造函数依赖注入的方式注入到控制器中,这样控制器就可以调用服务的方法。例如:
import { Controller, Get } from '@nestjs/common'; import { UserService } from './user.service'; @Controller('users') export class UsersController { constructor(private readonly userService: UserService) {} @Get() getUsers(): string { return this.userService.getUsers(); } }
private readonly userService: UserService
:通过构造函数注入 UserService
服务。this.userService.getUsers()
:调用 UserService
中的方法。模块用于组织和定义应用的各个部分。模块可以包含控制器、服务、提供者等。以下是如何创建一个模块的示例:
import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UserService } from './user.service'; @Module({ imports: [], controllers: [UsersController], providers: [UserService], }) export class UsersModule {}
imports
:可以引入其他模块。controllers
:模块注册的控制器列表。providers
:模块注册的服务列表。Nest框架可以与多种数据库集成,例如MySQL、MongoDB等。以下是如何集成MongoDB的示例:
npm install @nestjs/mongoose mongoose
在 src/app.module.ts
中配置MongoDB连接:
import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { UsersController } from './users.controller'; import { UserService } from './user.service'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost:27017/test'), ], controllers: [UsersController], providers: [UserService], }) export class AppModule {}
MongooseModule.forRoot
:配置MongoDB连接字符串。数据模型定义了数据库中的数据结构。例如,定义一个User模型:
import { Schema, Document } from 'mongoose'; import { User } from './user.entity'; export interface UserDocument extends Document { name: string; email: string; } export const UserSchema = new Schema({ name: String, email: String, });
模型定义后可以进行数据库的增删改查操作。例如:
import { Injectable } from '@nestjs/common'; import { Model } from 'mongoose'; import { UserDocument, UserSchema } from './user.model'; @Injectable() export class UserService { constructor(private readonly userModel: Model<UserDocument>) {} async createUser(user: User): Promise<UserDocument> { return this.userModel.create(user); } async getUsers(): Promise<UserDocument[]> { return this.userModel.find().exec(); } }
create
:创建新数据。find
:查询数据。exec
:执行查询操作。集成MySQL数据库需要安装 @nestjs/typeorm
和 typeorm
依赖:
npm install @nestjs/typeorm typeorm mysql2
在 src/app.module.ts
中配置MySQL连接:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserRepository } from './user.repository'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'test', entities: [UserRepository], synchronize: true, }), ], controllers: [UsersController], providers: [UserService], }) export class AppModule {}
数据库事务确保了数据库操作的原子性、一致性、隔离性、持久性(ACID)。Nest框架通过 typeorm
库支持事务操作。
安装依赖:
npm install typeorm
在 src/app.module.ts
中配置事务:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UsersModule } from './users.module'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'test', entities: [UserRepository], synchronize: true, }), UsersModule, ], }) export class AppModule {}
在服务中使用事务:
import { Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; import { UserRepository } from './user.repository'; @Injectable() export class UserService { constructor(private readonly userRepository: Repository<User>) {} async createUser(user: User): Promise<User> { const newEntity = this.userRepository.create(user); return this.userRepository.save(newEntity); } async getUsers(): Promise<User[]> { return this.userRepository.find(); } async createUserWithTransaction(user: User): Promise<User> { const queryRunner = this.userRepository.manager.queryRunner; await queryRunner.startTransaction(); try { const newUser = await this.userRepository.save({ ...user }); await queryRunner.commitTransaction(); return newUser; } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } }
startTransaction
:开始一个事务。commitTransaction
:提交事务。rollbackTransaction
:回滚事务。release
:释放查询运行器。CORS(跨域资源共享)是一种浏览器安全性策略,用于防范跨域请求中的恶意行为(如XSS攻击)。当浏览器接收到跨域请求时,会自动执行预检请求(Preflight Request),检查服务器是否允许该跨域请求。
Nest框架提供了内置的CORS中间件,可以通过配置 @nestjs/cors
来启用跨域访问。
npm install @nestjs/cors
在 main.ts
中启用CORS:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { CorsOptions, CorsOptionsFactory } from '@nestjs/common'; class CustomCorsOptions implements CorsOptionsFactory { createCorsOptions(): CorsOptions { return { origin: true, methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', preflightContinue: false, optionsSuccessStatus: 204, }; } } async function bootstrap() { const app = await NestFactory.create(AppModule); app.enableCors(new CustomCorsOptions().createCorsOptions()); await app.listen(3000); } bootstrap();
@nestjs/cors
:引入CORS中间件。enableCors
:启用CORS。环境变量可以在不同环境下(如开发、测试、生产)使用不同的配置。Nest框架支持环境变量的读取和使用。
npm install dotenv
创建 .env
文件,添加环境变量:
PORT=3000 DB_HOST=localhost DB_PORT=27017 DB_NAME=test
在 src/main.ts
中读取环境变量:
import * as dotenv from 'dotenv'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { CustomCorsOptions } from './main'; dotenv.config(); async function bootstrap() { const app = await NestFactory.create(AppModule); app.enableCors(new CustomCorsOptions().createCorsOptions()); const port = process.env.PORT || 3000; await app.listen(port); } bootstrap();
dotenv.config()
:读取 .env
文件中的环境变量。process.env.PORT
:从环境变量中读取端口配置。通过以上步骤,可以有效地管理不同环境下的配置,提高应用的可移植性和安全性。