nestjs模板构建、使用教程、功能的实现与封装
前提需要安装Node.js环境
- 定时执行任务
- 文件上传和下载
- 邮件服务(发送邮件)
- 任务队列 (排队处理数据)
- 监控服务器的性能、接口等
- 封装异常处理(统一返回错误格式)
- JWT鉴权,权限相关控制(注册/登陆)
- HttpModule请求第三方接口(Axios封装)
- 使用swagger生成API文档(提供给前端)
- 使用GraphQL做接口 (前端可自定义数据)
- 使用Typeorm操作数据库(Mysql的操作)
- logger监听接口请求(打印前端请求详情)
- 守卫验证角色 ( 判断是否有权限调用 )
- pipe管道转换参数类型(转换前端传递的值)
......
npm i -g @nestjs/cli
将 service-nest 替换成你自己的项目名称
nest new service-nest
更多命令查看 package.json文件
yarn start
or
npm start
如你希望文件变化项目便自动重启,就在后面加:dev
yarn start:dev
or
npm start:dev
访问 http://localhost:3000/ ,当你看到 Hello World! ,说明已正常运行。
import { NestFactory } from '@nestjs/core';
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('api'); // 配置路由前缀 http://xxx:3000/api/*
await app.listen(3000);
在src下几个重要的文件介绍
文件夹/文件 | 说明 |
---|---|
main.ts 项目入口 | 整个项目的入口文件 |
app.module.ts 模块集合 | 所有项目模块的集合 |
modules 主要工作 | 路由模块存放/前端请求的接口可能都在这 |
common 公共函数 | 存放公共方法/模块/类 |
config 配置文件 | 存放固定参数配置文件,如:数据库/邮件/微信等 |
tasks 定时任务 | 存放定时任务,如:定时更新任务、爬取页面等 |
templates 模板文件 | 存放模板,如:邮件/HTML/短信模板等 |
文件 | 快捷命令 | 说明 |
---|---|---|
controller | nest g co modules/ | 控制器处理get |
module | nest g mo modules/ | 负责功能模块引入、关联 |
service | nest g s modules/ | 负责返回结果、查询数据库、查询其他接口 |
resolver | nest g r modules/ | graphql |
entity | 不支持 | 管理数据库表结构 |
dto/ | 不支持 | 定义数据类型 |
*.spec.ts | 自动 | 相关测试文件 |
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'
import { XxxController } from './xxx.controller';
import { XxxService } from './xxx.service';;
import { XxxEntity } from './xxx.entity';
@Module({
imports: [TypeOrmModule.forFeature([XxxEntity])],
controllers: [XxxController],
providers: [XxxService],
exports: [
TypeOrmModule.forFeature([XxxEntity]),
],
})
export class XxxModule { }
import { Entity, PrimaryGeneratedColumn, ManyToOne, Column, BeforeInsert } from 'typeorm';
import { Exclude, Expose } from 'class-transformer';
@Entity({ name: 'xxx' }) // name 填入表名称,会自动创建这个表
export class XxxEntity {
@PrimaryGeneratedColumn({
comment: '自增ID'
})
id: number;
@Column('tinyint', {
nullable: false,
default: () => 0,
name: 'is_admin',
comment: '是否管理员? 1:是, 0:不是'
})
is_admin: number;
@Column({
length: 500,
comment: '名字'
})
name: string;
@Column('text')
description: string;
@Column()
filename: string;
@Column('int', {
nullable: false,
default: () => 1,
name: 'sort',
comment: '排序'
})
sort: number;
@Column('varchar', {
nullable: true,
length: 100,
name: 'url',
comment: 'url地址'
})
url: string | null;
@Exclude() // 表示排除字段
@Column('varchar', {
nullable: false,
length: 100,
name: 'password',
comment: '密码'
})
password: string;
// 插入数据库前先给密码加密
@BeforeInsert()
public makePassword() {
// this.password = makePassword(this.password)
}
// 检查密码是否正确
public checkPassword(password: string, sqlPassword: string) {
// return checkPassword(password, sqlPassword);
}
// 重新定义返回数据结构, 注意: 会导致上面的Exclude和Expose失效 !!!
public toResponseObject(isShowPassword = false): object {
const { password, ...params } = this;
if (isShowPassword) {
return Object.assign(isShowPassword, { password });
} else {
return params;
}
}
}
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateXxxDto } from './dto/create.xxx.dto';
import { XxxEntity } from './xxx.entity';
@Injectable()
export class XxxService {
constructor(@InjectRepository(XxxEntity) private readonly xxxRepository: Repository<XxxEntity>, ) { }
get(id: string): string {
return '使用了Get方法,传入ID为:' + id
}
create(body: CreateXxxDto): string {
return '使用了post请求,传入内容' + JSON.stringify(body)
}
query(): Promise<any> {
return this.xxxRepository.find() // 查询数据库
}
}
import { Controller, Get, Param, Body, Post } from '@nestjs/common';
import { XxxService } from './xxx.service';
import { CreateXxxDto } from './dto/create.xxx.dto';
@Controller('xxx')
export class XxxController {
constructor(
private readonly xxxService: XxxService,
) { }
@Get('all')
query() { // 查询数据库
return this.xxxService.query()
}
// 处理前端传过来的数据
@Get(':id')
get(@Param('id') id: string): string {
return this.xxxService.get(id)
}
@Post()
create(@Body() body: CreateXxxDto): string {
return this.xxxService.create(body)
}
}
dto/create.xxx.dto.ts
import { IsString, IsNotEmpty } from 'class-validator';
export class CreateXxxDto {
@IsString({ message: '用户名必须为字符类型' })
@IsNotEmpty({ message: '用户名不能为空' })
readonly name: string
@IsString({ message: '密码必须为字符串类型' })
@IsNotEmpty({ message: '密码不能为空' })
readonly pwd: string
}
npm i nestjs-config class-transformer class-validator
将src/config/* 下面的文件导入
ConfigModule.load(resolve(__dirname, 'config', '**/!(*.d).{ts,js}')), // 配置导入路径
*.forRootAsync({
// useFactory 和 inject 一起使用
useFactory: (config: ConfigService) => config.get('database'),
inject: [ConfigService]
})
// 相当于
import xxx from "src/config/xxx";
import { Entity, PrimaryGeneratedColumn, ManyToOne, Column } from 'typeorm';
import { Exclude, Expose } from 'class-transformer';
@Entity({ name: 'xxx' }) // name 填入表名称,会自动创建这个表
export class XxxEntity {
@PrimaryGeneratedColumn({
comment: '自增ID'
})
id: number;
@Exclude() // 表示排除字段
@Column('varchar', {
nullable: false,
length: 100,
name: 'password',
comment: '密码'
})
password: string;
}
验证数据
import { IsString, IsNotEmpty } from 'class-validator';
export class CreateXxxDto {
@IsString({ message: '用户名必须为字符类型' })
@IsNotEmpty({ message: '用户名不能为空' })
readonly name: string
@IsString({ message: '密码必须为字符串类型' })
@IsNotEmpty({ message: '密码不能为空' })
readonly pwd: string
}
基本上所有提供给前端的路由都导入到src/app.module.ts
import { Module } from '@nestjs/common';
import { XxxModule } from './modules/xxx/xxx.module';
@Module({
imports: [
XxxModule
],
})
export class AppModule { }
npm i -g @nestjs/cli
nest new x
yarn start:dev
- yarn start:dev
- 创建logger监听请求
- 使用异常处理 **ExceptionFilter **封装统一格式
- 添加pipe处理数据类型
- **swagger 或者 GraphQL **提供API给前端
- 构建路由常用四件套 [** controller + module + entity + service **]
- JWT 或者session 登陆/注册
- 守卫验证权限