Exceptionfilter异常过滤器怎么在nestjs中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
Nestjs的异常处理
Nestjs内置了默认的全局异常过滤器,处理能够转换成Httpexception的异常。
如果是Httpexception或其子类异常,那么会返回该异常的JSON格式:
{"exceptionCode":40005,"message":"自定义异常","path":"/"}
如果不是Httpexception或其子类异常,那么会返回:
{"statusCode":500,"message":"Internal server error"}
由于Nestjs采用了内置的默认异常处理,因此不会出现由于出现未捕获的异常导致程序崩溃。
由于内置异常处理返回值格式无法调整,因此自定义异常就显得又为正常。自定义异常可以使返回异常信息自定义,且可以增加自定义异常编码,方便客户端人员根据异常编码进行不同的展示。
如何自定义异常?
不重复造轮子是程序员的自我约束,首先我们新建我们自己的异常基类:
import { HttpException } from "@nestjs/common"; /** * 定义基础异常类 * * @export * @class BaseException * @extends {HttpException} */ export class BaseException extends HttpException { /** * Creates an instance of BaseException. * @param {number} exceptionCode 自定义异常编号 * @param {string} errorMessage 提示信息 * @param {number} statusCode 状态码 * @memberof BaseException */ constructor(public exceptionCode: number, public errorMessage: string, public statusCode: number) { super({ exceptionCode: exceptionCode, errorMessage: errorMessage }, statusCode); } /** * 获取自定义异常代码 * * @return {*} * @memberof BaseException */ getExceptionCode(): number { return this.exceptionCode; } getErrorMessage(): string { return this.errorMessage; } getStatusCode(): number { return this.statusCode; } }
然后我们新建一个未授权异常类型,其中增加了自定义异常代码:
import { HttpStatus } from "@nestjs/common"; import { BaseException } from "./base.exception"; export class UnCauhtException extends BaseException { constructor() { super(40000, "系统运行异常,请联系管理员!", HttpStatus.FORBIDDEN); } }
建立好了自定义异常,那么我们就需要处理未授权异常,首先新建自定义异常处理基类,请注意 此处我们使用的事Express:
import { ArgumentsHost, ExceptionFilter, HttpException } from "@nestjs/common"; import { HttpArgumentsHost } from "@nestjs/common/interfaces"; import { BaseException } from "src/exceptions/base.exception"; import { Response, Request } from "express"; /** * 异常基础类过滤器 * * @export * @class BaseExceptionFilter * @implements {ExceptionFilter<BaseException>} */ export abstract class BaseExceptionFilter implements ExceptionFilter<BaseException> { /** * 异常类捕获 * * @abstract * @param {BaseException} exception * @param {ArgumentsHost} host * @memberof BaseExceptionFilter */ abstract catch(exception: BaseException, host: ArgumentsHost); /** * 获取http请求上下文参数 * * @protected * @param {ArgumentsHost} host * @return {*} * @memberof BaseExceptionFilter */ protected getHttpContext(host: ArgumentsHost) { return host.switchToHttp(); } /** * 获取http 响应参数 * * @protected * @param {HttpArgumentsHost} httpContext * @return {*} * @memberof BaseExceptionFilter */ protected getResponse(httpContext: HttpArgumentsHost): Response { return httpContext.getResponse<Response>(); } /** * 获取http请求参数 * * @protected * @param {HttpArgumentsHost} httpContext * @return {*} * @memberof BaseExceptionFilter */ protected getRequest(httpContext: HttpArgumentsHost): Request { return httpContext.getRequest<Request>(); } /** * 写入异常信息到客户端 * * @param {ArgumentsHost} host * @param {BaseException} exception * @memberof BaseExceptionFilter */ protected writeToClient(host: ArgumentsHost, exception: BaseException) { const ctx = this.getHttpContext(host); if(exception instanceof BaseException){ this.getResponse(ctx).status(exception.statusCode).json({ exceptionCode: exception.getExceptionCode(), message: exception.getErrorMessage(), path: this.getRequest(ctx).url }); }else { const httpException=exception ; this.getResponse(ctx).status(500).json({ message: "未处理的异常", path: this.getRequest(ctx).url }); } } }
新建未授权异常处理:
import { ArgumentsHost, Catch } from "@nestjs/common"; import { AuthException } from "src/exceptions/auth.exception"; import { BaseException } from "src/exceptions/base.exception"; import { BaseExceptionFilter } from "./base.exception.filter"; @Catch(AuthException) export class AuthExceptionFilter extends BaseExceptionFilter { constructor(){ super(); console.log("授权异常构造函数初始化"+new Date().toISOString()); } catch(exception: AuthException, host: ArgumentsHost) { exception.exceptionCode=40002; console.log("授权异常执行"+new Date().toISOString()); this.writeToClient(host,exception); } }
针对未授权异常处理类,进行几点说明:
增加了Catch注解,只捕获Authexception的异常,其他类型的异常此类不进行处理
继承自定义异常处理类Baseexceptionfilter
异常处理类可应用于method、controller、全局,甚至同一个Controller可以定义多个自定义异常类
import { Controller, ForbiddenException, Get, HttpException, HttpStatus, UseFilters } from '@nestjs/common'; import { AppService } from './app.service'; import { AuthException } from './exceptions/auth.exception'; import { BusinessException } from './exceptions/business.exception'; import { UnCauhtException } from './exceptions/uncauht.exception'; import { AuthExceptionFilter } from './filters/auth.exception.filter'; import { BusinessExceptionFilter } from './filters/business.exception.filter'; /** * 带有单个路由的基本控制器示例ff */ @UseFilters(AuthExceptionFilter,BusinessExceptionFilter) @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() getHello(): string { //throw new Error("666"); throw new BusinessException("自定义异常",HttpStatus.OK); throw new AuthException(); throw new HttpException("自定义异常",HttpStatus.FORBIDDEN); return this.appService.getHello(); } @Get("name") getName():string { return "guozhiqi"; } }
几点说明:
我们使用Usefilters注解进行异常过滤器的添加
我们在Appcontroller中定义了两种不同类型的自定义异常处理类
也就是我们Appcontroller中抛出的异常,只要是我们定义的这两种,那么都可以被正常处理。
几点疑问
Usefitlers中我们自定义的异常处理类会初始化几次?
答案:我们通过类型注册到Appcontroller的自定义异常类只会在程序初始化的时候初始化一次。也就是说程序启动之后,每个
controller、每个method定义了哪些异常处理类都已经确定。
如果我们捕获到异常,但不进行任何处理,会发生什么?
答案:如果我们的异常处理方法什么也不做,那么恭喜你,会成功的将浏览器请求hang死,因为异常未处理,那么浏览器会一直得不到响应。
多个异常之间的处理顺序如何?
答案:如果多个异常处理均可以捕获到该异常,那么只有第一个有效,也就是说异常处理类和 中间件不同,异常处理类只能其中一个处理,而中间件需要都进行处理。
Nestjs的@Usefilters 像谁?
首先从JS角度来看,像Angular,如果往后端看,最像Spring。
Nestjs的异常处理并不复杂,复杂的是需要我们针对不同类型的异常进行处理,提取异常的共性。
关于Exceptionfilter异常过滤器怎么在nestjs中使用问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。