连接 MySql 数据库
作为一个服务端框架那肯定离不开对数据库的操作,而 Nest 连接数据库以及操作数据库也是很简单的,毕竟我们有好用的工具啊,先安装
npm install @nestjs/typeorm typeorm mysql -S
然后在 app.module.ts 进行一个导入,配置一下自己的数据库用户名,密码等等,这里如果用本地数据库的话需要自己先在电脑安装数据库
import { Module } from "@nestjs/common"; import { AppController } from "./app.controller"; import { AppService } from "./app.service"; import { UserModule } from "./user/user.module"; import { TypeOrmModule } from "@nestjs/typeorm"; @Module({ imports: [ UserModule, TypeOrmModule.forRoot({ type: "mysql", host: "localhost", port: 3306, username: "root", password: "root", database: "ceshi", entities: ["dist/**/*.entity{.ts,.js}"], synchronize: true, }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
然后我们可以到 user/entities/user.entity.ts 中简单建一个用户表
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; @Entity("user") export class UserEntity { @PrimaryGeneratedColumn() id: number; // 标记为主键,值自动生成 @Column({ length: 20 }) username: string; @Column({ length: 20 }) password: string; @Column({ type: "timestamp", default: () => "CURRENT_TIMESTAMP" }) create_time: Date; @Column({ type: "timestamp", default: () => "CURRENT_TIMESTAMP" }) update_time: Date; }
保存过后就会发现 user 表就被自动创建了
CRUD
接下来我们根据前端传来的参数对数据库进行一个简单的 crud 操作,注意这里只是演示,少了一些逻辑判断。 首先在user.module.ts
中导入数据库相关东西
import { Module } from "@nestjs/common"; import { UserService } from "./user.service"; import { UserController } from "./user.controller"; import { UserEntity } from "./entities/user.entity"; import { TypeOrmModule } from "@nestjs/typeorm"; @Module({ imports: [TypeOrmModule.forFeature([UserEntity])], controllers: [UserController], providers: [UserService], }) export class UserModule {}
来到create-user.dto.ts
定义一下接收前端传来的参数
export class CreateUserDto { username: string; password: string; }
然后在user.service.ts
进行数据库数据的插入
import { Injectable } from '@nestjs/common'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { UserEntity } from './entities/user.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; @Injectable() export class UserService { constructor( @InjectRepository(UserEntity) private userRepository: Repository<UserEntity>, ) {} async create(createUserDto: CreateUserDto) { this.userRepository.save(createUserDto); return await this.userRepository.save(createUserDto); } }
在 ApiFox 模拟一个请求,会发现插入成功了
同时我们查看我们的 user 表出现了一条数据
我们再看一下查询,来到 user.service.ts 中的 findAll 方法
async findAll() { return await this.userRepository.find(); }
因为 findAll 在 controller 中是 get 装饰,所以需要使用 get 请求
如果我们想加条件,可以这样写
async findAll() { return await this.userRepository.find({ where: { id: 1 } }); }
对于数据的更新相对麻烦一点,比如我们想要更新一条数据可以这样写
在user.controller.ts
中我们需要接收前端传来的一个 id(动态路由传来的)以及 body
@Patch(':id') update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.userService.update(+id, updateUserDto); }
然后在user.service.ts
中的 update 方法中,根据 id 来更新前端传来的数据,注意这里用到了 TypeOrm 的查询构造器,想了解的可以到TypeOrm查看
async update(id: number, updateUserDto: UpdateUserDto) { const qb = await this.userRepository.createQueryBuilder(); return await qb.update().set(updateUserDto).where({ id }).execute(); }
我们可以使用Patch
方法在 apiFox 中试一下
我们可以看到数据更新成功啦~
最后看一下删除,其实和更新差不多
async remove(id: number) { const qb = await this.userRepository.createQueryBuilder(); return await qb.delete().where({ id }).execute(); }
其实对于数据库操作的方法还有很多中,这里只是列举了其中的一小部分。想要熟练操作数据库还需要长期的日积月累才行
统一接口返回形式
通过上面的一通操作,细心的小伙汁肯定发现了上面接口返回的数据是个什么玩意.要状态没状态,要描述没描述的,这样拿给前端前端不得揍死你。所以为了把最好的留给前端,我们还需要对接口返回进行一个统一数据封装
一般接口返回的数据大致格式可能如下
{ data:业务参数, code:状态码, describe:状态描述 ... }
首先我们使用命令新建一个过滤器,用来抛出我们需要返回给前端的错误码以告知前端传来的是错误请求
nest g filter common/filter/http-exception
然后修改一下http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, } from '@nestjs/common'; import { Request, Response } from 'express'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception.getStatus(); response.status(status).json({ code: status, timestamp: new Date().toISOString(), path: request.url, }); } }
在 main.ts 中注册
import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; import { HttpExceptionFilter } from "./common/filter/http-exception/http-exception.filter"; async function bootstrap() { const app = await NestFactory.create(AppModule); //看这里看这里看这里~ app.useGlobalFilters(new HttpExceptionFilter()); await app.listen(3000); } bootstrap();
这时候我们随便找个接口抛出一个错误码试一下,就你了findAll
方法
async findAll() { throw new HttpException('错误的请求', 401); return await this.userRepository.find(); }
然后我们在 ApiFox 试一下
然后我们再创建一个拦截器对请求成功的数据进行格式化
同样的使用
nest g interceptor common/interceptor/transform
创建一个拦截器,直接把官网示例抄过来transform.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, } from "@nestjs/common"; import { Observable } from "rxjs"; import { map } from "rxjs/operators"; export interface Response<T> { data: T; } @Injectable() export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> { intercept( context: ExecutionContext, next: CallHandler ): Observable<Response<T>> { return next .handle() .pipe(map((data) => ({ code: 200, data, describe: "请求成功" }))); } }
和过滤器一样在 main.ts 中注册
app.useGlobalInterceptors(new TransformInterceptor());
然后试一下查询接口
到这里我们就完成了返回结果的一个简单封装
写在最后
NestJS 的功能远远不止文章提到的这些,毕竟一个框架不是简单的一篇文章就能讲完的。就像本文标题一样,本篇文章旨在带领大家走进 NestJS 的大门,如果对 NestJS 感兴趣的小伙伴可以在以后的工作学习中慢慢探索,加油吧少年,祝你早日成为全干工程师!
需要文中代码的同学可以直接点击nest-template获取