CodeWalk

NestJS 异常过滤器(Exception Filter)与全局错误处理

作者:古法程序员 · 2026-05-30 12:55

请解释 NestJS 的异常过滤器(Exception Filter)机制,包括内置异常类(HttpException/BadRequestException)、自定义异常过滤器、以及全局过滤器注册方式。

回答

古法程序员

NestJS 异常处理层级

控制器 → 拦截器 → 守卫 → 管道 → 异常过滤器(最外层)

1. 内置异常类

import { HttpException, HttpStatus } from '@nestjs/common';

// 基础
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
// 带自定义响应
throw new HttpException({
  status: HttpStatus.FORBIDDEN,
  error: '无权访问',
  timestamp: new Date().toISOString(),
}, HttpStatus.FORBIDDEN);

// 预定义异常
throw new BadRequestException('参数错误');
throw new UnauthorizedException('未登录');
throw new NotFoundException('资源不存在');
throw new ConflictException('数据冲突');

2. 自定义异常过滤器

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Response } from 'express';

@Catch(HttpException)  // 捕获 HttpException 及其子类
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    const exceptionResponse = exception.getResponse();
    
    response.status(status).json({
      code: status,
      message: typeof exceptionResponse === 'string'
        ? exceptionResponse
        : (exceptionResponse as any).message || '服务器错误',
      timestamp: new Date().toISOString(),
      path: ctx.getRequest().url,
    });
  }
}

// 捕获所有异常(包括非 HttpException)
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) { ... }
}

3. 注册方式

// 全局注册(main.ts)
app.useGlobalFilters(new HttpExceptionFilter());

// 或模块级别注册
@Module({
  providers: [{
    provide: APP_FILTER,
    useClass: HttpExceptionFilter,
  }],
})

// 方法/控制器级别
@UseFilters(new HttpExceptionFilter())

最佳实践:全局统一错误格式,区分开发/生产环境的错误详情。