关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

Vue3 + Nest 实现权限管理系统 后端篇(一):NestJS入门与基础配置(下)

发布时间:2023-06-27 00:00:37


统一的异常处理器



有时候前端会进行一些错误的请求,这时候我们需要返回给他一个异常告知他的请求有问题,我们可以使用 NestJS 内置的异常处理HttpException比如

throw new HttpException('您无权登录', HttpStatus.FORBIDDEN);

   

客户端就会收到

{  "statusCode": 403,  "message": "您无权登录" }

   

但是这样不够灵活,所以我们可以新建一个异常过滤器进行自定义的操作

nest g filter common/filter/http-exception

   

然后修改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();  const request = ctx.getRequest();  const status = exception.getStatus();  response.status(status).json({  code: status,  timestamp: new Date().toISOString(),  path: request.url,  describe: exception.message,  });  } }

   

最后在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();

   

user.service.ts的 findAll 测试一下

async findAll() {  throw new HttpException('禁止访问', HttpStatus.FORBIDDEN);  return await this.userRepository.find();  }

   

前端就会收到错误信息的返回


返回格式化拦截器



我们还需要一个返回格式的拦截器对请求成功(状态码为 2xx)的数据进行一个格式化,比如返回这样的格式

{  data:业务参数,  code:状态码,  describe:状态描述  ... }

   

同样的先执行

nest g interceptor common/interceptor/transform

   

创建一个拦截器,按照官网示例给的复制过来

import {  Injectable,  NestInterceptor,  ExecutionContext,  CallHandler, } from "@nestjs/common"; import { Observable } from "rxjs"; import { map } from "rxjs/operators"; export interface Response{  data: T; } @Injectable() export class TransformInterceptor implements NestInterceptor<T, Response> {  intercept(  context: ExecutionContext,  next: CallHandler  ): Observable<Response> {  return next  .handle()  .pipe(map((data) => ({ code: 200, data, describe: "请求成功" })));  } }

   

和过滤器一样在main.ts中注册

import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; import { HttpExceptionFilter } from "./common/filter/http-exception/http-exception.filter"; import { TransformInterceptor } from "./common/interceptor/transform/transform.interceptor"; async function bootstrap() {  const app = await NestFactory.create(AppModule);  //看这里看这里看这里~  app.useGlobalFilters(new HttpExceptionFilter());  app.useGlobalInterceptors(new TransformInterceptor());  await app.listen(3000); } bootstrap();

   

我们再将findAll函数改为请求成功的状态

async findAll() {  return await this.userRepository.find();  }

   

进行请求就会发现数据已经被格式化了

但是这样做之后我们会发现请求成功的 code 只能是 200,一般项目中请求成功还需要很多业务异常状态码返回给前端,所以我们需要新建一个抛出业务异常的类ApiException我们先创建common/enums/api-error-code.enum.ts用于存放我们的业务状态码,这里简单写几个

export enum ApiErrorCode {  SUCCESS = 200, // 成功  USER_ID_INVALID = 10001, // 用户id无效  USER_NOTEXIST = 10002, // 用户id无效 }

   

然后在http-exception中新建api.exception.ts,创建一个ApiException类继承HttpException,接受三个参数错误信息,错误码code,http状态码(默认是200)

import { HttpException, HttpStatus } from '@nestjs/common'; import { ApiErrorCode } from '../../enums/api-error-code.enum'; export class ApiException extends HttpException {  private errorMessage: string;  private errorCode: ApiErrorCode;  constructor(  errorMessage: string,  errorCode: ApiErrorCode,  statusCode: HttpStatus = HttpStatus.OK,  ) {  super(errorMessage, statusCode);  this.errorMessage = errorMessage;  this.errorCode = errorCode;  }  getErrorCode(): ApiErrorCode {  return this.errorCode;  }  getErrorMessage(): string {  return this.errorMessage;  } }

   

然后修改http-exception.filter.ts,可以判断exception是否在ApiException原型链上来确定是调用的是ApiException还是HttpException

import {  ExceptionFilter,  Catch,  ArgumentsHost,  HttpException, } from '@nestjs/common'; import { Request, Response } from 'express'; import { ApiException } from './api.exception'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter {  catch(exception: HttpException, host: ArgumentsHost) {  const ctx = host.switchToHttp();  const response = ctx.getResponse();  const request = ctx.getRequest();  const status = exception.getStatus();  if (exception instanceof ApiException) {  response.status(status).json({  code: exception.getErrorCode(),  timestamp: new Date().toISOString(),  path: request.url,  describe: exception.getErrorMessage(),  });  return;  }  response.status(status).json({  code: status,  timestamp: new Date().toISOString(),  path: request.url,  describe: exception.message,  });  } }

   

然后在 findAll 函数中抛出一个业务异常

async findAll() {  throw new ApiException('用户不存在', ApiErrorCode.USER_NOTEXIST);  return await this.userRepository.find();  }

   

然后进行请求

此时你会发现请求是成功的,但是 code 值是异常的,符合我们的预期

到这里NestJS的基本配置已经做完了,后续便可直接开始我们业务的开发了,欢迎点赞收藏加关注!


/template/Home/leiyu/PC/Static