Nestjs(五)异常处理方式(异常过滤器)

本文介绍了如何在NestJS应用中创建和使用异常过滤器,包括局部接口级别的处理和全局注册。重点讲解了如何将捕获的异常转换为HTTP响应返回给前端,并提供了两种全局异常处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

  • 异常过滤器 - 官方文档

  • 创建异常过滤器 http-exception.filter.ts 文件

    $ nest g f http-exception
    
    // 这是创建后的文件初始内容
    import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
    
    @Catch()
    export class HttpExceptionFilter<T> implements ExceptionFilter {
      catch(exception: T, host: ArgumentsHost) {
        // 这里就是拦截到的异常,需要处理并抛出给到前台方便直观看到问题...
        // 输出拦截到的错误异常
        console.log(exception)
      }
    }
    
  • 做下小改造,上面初始化的只会在 node 控制台输出,现在改造成将这个异常抛出到接口返回,前端接口就能看得到:

    import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
    // 如果不引用,可能会导致类型关联错误
    import { Response, Request } from 'express';
    
    // 捕获 HttpException 错误;  如果 @Catch() 里面没有参数, 则捕获所有错误
    // 可以支持多个 @Catch(HttpException, xxx, xxx)
    // 支持的内置异常列表文档:https://docs.nestjs.cn/10/exceptionfilters?id=%e5%86%85%e7%bd%aehttp%e5%bc%82%e5%b8%b8
    @Catch(HttpException)
    export class HttpExceptionFilter<T> implements ExceptionFilter {
      // exception:当前正在处理的异常对象
      // host:传递给原始处理程序的一个包装(Response/Request)引用参数
      catch(exception: HttpException, host: ArgumentsHost) {
        // 获取上下文
        const ctx = host.switchToHttp();
        // 响应对象,跟接口中 @Response @Res 取到的一样
        const response = ctx.getResponse<Response>();
        // 请求对象,跟接口中 @Request @Req 取到的一样
        const request = ctx.getRequest<Request>();
        // 异常状态
        const status = exception.getStatus();
        // 抛出错误日志
        response
          .status(status)
          .json({
            dzm: '测试字段',
            statusCode: status,
            timestamp: new Date().toISOString(),
            path: request.url
          });
      }
    }
    

二、局部支持异常处理

image.png

  • 某个接口

    import { Controller, Get, Body, Query, Post, Param, Request, Req, Res, Redirect, HttpCode, HttpException, HttpStatus, UseFilters } from '@nestjs/common';
    import { UserService } from './user.service';
    // 这里也需要引入
    import { HttpExceptionFilter } from 'src/http-exception.filter';
    
    @Controller('user')
    export class UserController {
      constructor(private readonly userService: UserService) { }
    
      @Get('/dzm')
      // 添加上过滤器
      @UseFilters(new HttpExceptionFilter())
      getDzm(@Req() req: any, @Res() res: any): any {
        // 故意抛出异常进行测试
        throw new HttpException('Forbidden', HttpStatus.FORBIDDEN)
        res.send(req.query)
      }
    }
    
  • 某个控制器下的所有接口

    import { Controller, Get, Body, Query, Post, Param, Request, Req, Res, Redirect, HttpCode, HttpException, HttpStatus, UseFilters } from '@nestjs/common';
    import { UserService } from './user.service';
    import { HttpExceptionFilter } from 'src/http-exception.filter';
    
    @Controller('user')
    @UseFilters(new HttpExceptionFilter())
    export class UserController {
      constructor(private readonly userService: UserService) { }
    
      @Get('/dzm')
      getDzm(@Req() req: any, @Res() res: any): any {
        // 故意抛出异常进行测试
        throw new HttpException('Forbidden', HttpStatus.FORBIDDEN)
        res.send(req.query)
      }
    }
    

三、全局异常处理

  • 方式一:main.ts,无法注入依赖

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import { HttpExceptionFilter } from './http-exception.filter';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      // 全局注册异常过滤器
      app.useGlobalFilters(new HttpExceptionFilter())
      await app.listen(3000);
    }
    bootstrap();
    
  • 方式二: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 { LoginModule } from './login/login.module';
    import { APP_FILTER } from '@nestjs/core';
    import { HttpExceptionFilter } from './http-exception.filter';
    
    @Module({
      imports: [UserModule, LoginModule],
      controllers: [AppController],
      providers: [
        AppService,
        // 这样注册即可,效果一样,可以根据需要使用此技术添加任意数量的过滤器
        {
          provide: APP_FILTER,
          useClass: HttpExceptionFilter,
        },
      ],
    })
    export class AppModule { }
    
### 创建和使用异常过滤器NestJS 中,异常过滤器用于捕获并处理出的异常。通过定义自定义异常过滤器可以集中管理应用程序中的错误响应逻辑。 #### 定义自定义异常过滤器 为了创建一个新的异常过滤器,需继承 `ExceptionFilter` 接口,并实现其唯一的抽象方法——`catch(exception, host)` 方法: ```typescript 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({ statusCode: status, timestamp: new Date().toISOString(), path: request.url, }); } } ``` 此代码片段展示了如何构建一个 HTTP 异常处理器[^1]。 #### 应用异常过滤器 一旦定义好了异常过滤器,则可以通过多种方式将其应用于同的上下文中: - **局部应用**:可以在特定路由处理器中注册该过滤器,仅影响单个端点的行为。 ```typescript @Controller('cats') export class CatsController { @Post() @UseFilters(new HttpExceptionFilter()) create(@Body() createCatDto: CreateCatDto) {} } ``` 上述例子说明了怎样在一个 POST 请求下指定使用 `HttpExceptionFilter` 来拦截可能发生的HTTP级别的异常状况。 - **全局范围内的应用**:如果希望在整个项目范围内生效的话,可在主模块文件内设置全局性的异常过滤器配置。 ```typescript async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new AllExceptionsFilter()); await app.listen(3000); } bootstrap(); ``` 这里演示的是将名为 `AllExceptionsFilter` 的过滤器设为整个项目的默认异常处理器的方式[^2]。 需要注意的是,在存在多个异常过滤器的情况下,它们会按照声明顺序依次尝试匹配所发生的具体异常类型;因此排列位置对于最终效果有着直接影响[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡尔特斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值