为了账号安全,请及时绑定邮箱和手机立即绑定

Nest后端开发入门教程

概述

本文详细介绍了Nest框架的核心特点与优势,包括模块化结构、依赖注入、装饰器模式以及高性能等特性,帮助开发者更好地理解Nest后端开发。此外,文章还提供了安装与环境配置、快速搭建Nest项目、控制器与路由、服务与模块、数据库集成、跨域支持及环境变量配置等实用指南。

Nest框架简介
什么是Nest框架

Nest框架是一个用于构建高效、可扩展的服务器端JavaScript应用程序的框架。它基于现代JavaScript(TypeScript)开发,使用了最新的ES2015+语言特性。Nest框架提供了模块化结构,允许开发者利用装饰器、依赖注入等特性,构建复杂的业务逻辑和API接口。

Nest框架的核心特点与优势

Nest框架的核心特点与优势包括:

  1. 模块化结构:Nest允许开发者通过模块(Module)来组织代码,每个模块可以包含控制器(Controller)、服务(Service)、提供者(Provider)等,这样可以保持代码的清晰和可维护性。
  2. 依赖注入:Nest中的所有服务都可以通过依赖注入的方式进行配置和使用,这种方式提高了代码的可测试性和可重用性。
  3. 装饰器模式:利用装饰器模式,Nest框架提供了丰富的元数据定义,使得开发者可以方便地为类和方法添加额外的行为和元数据。
  4. 可插拔中间件:Nest框架集成了Express中间件,允许使用各种Express中间件来处理请求,例如处理静态文件、路由、错误处理等。
  5. 高性能:Nest是基于Node.js构建的,能够充分利用Node.js的异步非阻塞I/O特性,从而提供高性能的网络服务。
安装与环境配置

安装Nest框架需要Node.js环境,建议使用Node.js版本14或更高版本。可以通过以下步骤安装Node.js和Nest CLI(命令行工具):

安装Node.js

  1. 访问Node.js官网下载最新版本的Node.js。
  2. 按照下载页面的说明完成安装。
  3. 使用 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项目的步骤:

  1. 打开命令行工具。
  2. 运行命令 nest new <项目名称>,例如创建一个名为 my-nest-app 的项目:
    nest new my-nest-app
  3. 此命令会创建一个新的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

创建一个简单的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!" 输出。

控制器(Controller)与路由
创建控制器

控制器用于处理HTTP请求。Nest框架中,控制器通过装饰器来定义路由和HTTP动词。以下是一个控制器的示例:

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

@Controller('users')
export class UsersController {
  // 更多方法...
}
  • @Controller('users'):定义一个路由前缀,所有该控制器中的方法都会加上这个前缀。
定义HTTP方法与路由

控制器中的方法通过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 参数。
服务(Service)与模块(Module)
如何创建服务

服务用于处理业务逻辑,通常将业务逻辑封装在服务中,然后通过依赖注入的方式供控制器使用。以下是如何创建一个服务的示例:

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:模块注册的服务列表。
数据库集成
连接数据库(如MySQL、MongoDB)

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数据库集成示例

集成MySQL数据库需要安装 @nestjs/typeormtypeorm 依赖:

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)与环境变量配置
什么是CORS

CORS(跨域资源共享)是一种浏览器安全性策略,用于防范跨域请求中的恶意行为(如XSS攻击)。当浏览器接收到跨域请求时,会自动执行预检请求(Preflight Request),检查服务器是否允许该跨域请求。

配置Nest应用支持CORS

Nest框架提供了内置的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:从环境变量中读取端口配置。

通过以上步骤,可以有效地管理不同环境下的配置,提高应用的可移植性和安全性。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消