简介
Nest 是一个用于构高效,可扩展的 Node.js 服务端应用程序的框架…… 它使用渐进式 JavaScript,内置并完全支持 TypeScript
特点:
基于 Node:对前端友好
服务端应用框架:主要用于服务端接口开发
高效,可扩展:体现在 Nest 各个功能模块之间的架构是解耦的、容易进行组合的
渐进式:不需要一开始掌握它的全部功能特性,后续可根据业务需要逐步叠加功能。
Nest 由 TS 开发,完全支持 TS
应用场景:
首先是最基础的,做服务端开发;
其次,支持服务端扩展,比如:安全、鉴权、队列、日志等
技术架构的支持:微服务,序列化等
安装与使用
1 2 3
| npm i @nestjs/cli nest new project npm run start
|
目录结构src如下:
入口文件为main.ts
创建module:
1
| nest g module user server
|
在目录不存在时生成src/server/user目录,并在user目录下添加user.module.ts文件,同时会在跟模块app.module.ts下自动引入UserModule
创建controller:
1
| nest g controller user server
|
controller
就类似前端的路由,负责处理客户端传入的请求和服务端返回的响应。
1 2 3 4 5 6 7 8 9 10 11
| import { Controller, Get } from '@nestjs/common';
@Controller('user') export class UserController { @Get('users') findAll(): string { return "用户信息"; } } findAll方法可以写成异步方法
|
创建provider:
1
| nest g service user server
|
我们的 controller
接收到了一个用户的查询请求,但不能直接在 controller
中去查询数据库并返回,而是要将查询请求交给 provider
来处理,所以创建了一个 UserService
,用来提供数据库操作服务。还可以用来做一些用户校验,比如使用 JWT
对用户权限进行校验的策略,就可以写成一个策略类,放到 provider
中,为模块提供相应的服务。
连接数据库(以MongoDB为例)
安装Mongoose:
1
| npm install mongoose @nestjs/mongoose --save
|
Nest官方提供了Mongoose的封装,用来操作数据库,连接数据之前,我们要先在根模块,也就是 app.module.ts
中引入 Mongoose
的连接模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { UserModule } from './server/user/user.module';
@Module({ imports: [MongooseModule.forRoot('mongodb://localhost/xxx'), UserModule], controllers: [AppController], providers: [AppService] }) export class AppModule {}
|
由于mongoose模块没有声明文件,控制台可能会报错,所以需要安装一下@types/mongoose:
1
| npm install @types/mongoose --dev 或者 yarn add @types/mongoose --dev
|
创建数据表:
在 src/server/user
文件夹下创建一个 user.schema.ts
文件,定义一个数据表的格式:
1 2 3 4 5 6 7 8
| import { Schema } from 'mongoose';
export const userSchema = new Schema({ _id: { type: String, required: true }, user_name: { type: String, required: true }, password: { type: String, required: true } });
|
修改user.module.ts文件:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { UserController } from './user.controller'; import { userSchema } from './user.schema'; import { UserService } from './user.service';
@Module({ imports: [MongooseModule.forFeature([{ name: 'Users', schema: userSchema }])], controllers: [UserController], providers: [UserService] }) export class UserModule {}
|
操作数据库:
打开 user.service.ts
文件,为 UserService
类添加一个构造函数,让其在实例化的时候能够接收到数据库 Model
,这样才能在类中的方法里操作数据库。
定义方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { CreateUserDTO } from './user.dto'; import { User } from './user.interface';
@Injectable() export class UserService { constructor(@InjectModel('Users') private readonly userModel: Model<User>) {}
async findAll(): Promise<User[]> { const users = await this.userModel.find(); return users; }
async findOne(_id: string): Promise<User> { return await this.userModel.findById(_id); }
async addOne(body: CreateUserDTO): Promise<void> { await this.userModel.create(body); }
async editOne(_id: string, body: EditUserDTO): Promise<void> { await this.userModel.findByIdAndUpdate(_id, body); }
async deleteOne(_id: string): Promise<void> { await this.userModel.findByIdAndDelete(_id); } } 因为 mongoose 操作数据库其实是异步的,所以这里我们使用 async 函数来处理异步的过程。
好奇的同学会发现,这里突然出现了两个文件,一个是 user.interface.ts,另一个是 user.dto.ts,我们现在来创建一下:
import { Document } from 'mongoose';
export interface User extends Document { readonly _id: string; readonly user_name: string; readonly password: string; }
export class CreateUserDTO { readonly _id: string; readonly user_name: string; readonly password: string; }
export class EditUserDTO { readonly user_name: string; readonly password: string; }
|
设置路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; import { CreateUserDTO, EditUserDTO } from './user.dto'; import { User } from './user.interface'; import { UserService } from './user.service';
interface UserResponse<T = unknown> { code: number; data?: T; message: string; }
@Controller('user') export class UserController { constructor(private readonly userService: UserService) {}
@Get('users') async findAll(): Promise<UserResponse<User[]>> { return { code: 200, data: await this.userService.findAll(), message: 'Success.' }; }
@Get(':_id') async findOne(@Param('_id') _id: string): Promise<UserResponse<User>> { return { code: 200, data: await this.userService.findOne(_id), message: 'Success.' }; }
@Post() async addOne(@Body() body: CreateUserDTO): Promise<UserResponse> { await this.userService.addOne(body); return { code: 200, message: 'Success.' }; }
@Put(':_id') async editOne( @Param('_id') _id: string, @Body() body: EditUserDTO ): Promise<UserResponse> { await this.userService.editOne(_id, body); return { code: 200, message: 'Success.' }; }
@Delete(':_id') async deleteOne(@Param('_id') _id: string): Promise<UserResponse> { await this.userService.deleteOne(_id); return { code: 200, message: 'Success.' }; } }
|
此时向接口发送请求,即可拿到数据库的数据…
内容转载至:https://zhuanlan.zhihu.com/p/267286129