本文详细介绍了Nest框架的核心特点与优势,包括模块化结构、依赖注入、装饰器模式以及高性能等特性,帮助开发者更好地理解Nest后端开发。此外,文章还提供了安装与环境配置、快速搭建Nest项目、控制器与路由、服务与模块、数据库集成、跨域支持及环境变量配置等实用指南。
Nest框架简介 什么是Nest框架Nest框架是一个用于构建高效、可扩展的服务器端JavaScript应用程序的框架。它基于现代JavaScript(TypeScript)开发,使用了最新的ES2015+语言特性。Nest框架提供了模块化结构,允许开发者利用装饰器、依赖注入等特性,构建复杂的业务逻辑和API接口。
Nest框架的核心特点与优势Nest框架的核心特点与优势包括:
- 模块化结构:Nest允许开发者通过模块(Module)来组织代码,每个模块可以包含控制器(Controller)、服务(Service)、提供者(Provider)等,这样可以保持代码的清晰和可维护性。
- 依赖注入:Nest中的所有服务都可以通过依赖注入的方式进行配置和使用,这种方式提高了代码的可测试性和可重用性。
- 装饰器模式:利用装饰器模式,Nest框架提供了丰富的元数据定义,使得开发者可以方便地为类和方法添加额外的行为和元数据。
- 可插拔中间件:Nest框架集成了Express中间件,允许使用各种Express中间件来处理请求,例如处理静态文件、路由、错误处理等。
- 高性能:Nest是基于Node.js构建的,能够充分利用Node.js的异步非阻塞I/O特性,从而提供高性能的网络服务。
安装Nest框架需要Node.js环境,建议使用Node.js版本14或更高版本。可以通过以下步骤安装Node.js和Nest CLI(命令行工具):
安装Node.js
- 访问Node.js官网下载最新版本的Node.js。
- 按照下载页面的说明完成安装。
- 使用
node -v
命令检查Node.js版本。
安装Nest CLI
安装Nest CLI可以通过npm(Node.js的包管理器)完成,执行以下命令:
npm i -g @nestjs/cli
此命令会全局安装Nest CLI工具,使其可以用于任何Nest项目中。
快速搭建Nest项目 创建新的Nest项目使用Nest CLI工具可以快速创建新的Nest项目。以下是创建Nest项目的步骤:
- 打开命令行工具。
- 运行命令
nest new <项目名称>
,例如创建一个名为my-nest-app
的项目:nest new my-nest-app
- 此命令会创建一个新的Nest项目,并初始化所需的依赖和文件。
一个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应用支持CORSNest框架提供了内置的CORS中间件,可以通过配置 @nestjs/cors
来启用跨域访问。
安装依赖
npm install @nestjs/cors
配置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
:从环境变量中读取端口配置。
通过以上步骤,可以有效地管理不同环境下的配置,提高应用的可移植性和安全性。