如何在NestJS中实现全局统一自定义响应格式?
在NestJS中实现统一自定义响应格式
要实现你需要的统一响应格式,核心是利用NestJS的拦截器(处理成功响应)和异常过滤器(处理异常响应),全局注册后即可对所有控制器的请求生效。
一、实现成功响应拦截器
拦截器可以在控制器返回结果后,统一包装成你需要的格式。创建一个TransformInterceptor:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class TransformInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { // 获取当前请求的URL和方法 const request = context.switchToHttp().getRequest(); const requestInfo = { url: request.url, method: request.method, }; // 包装响应数据 return next.handle().pipe( map((data) => ({ status: 'success', code: 200, // 可根据业务需求替换为自定义业务码 message: '请求成功', // 支持从控制器返回值中动态读取,比如data.message data: data, request: requestInfo, })), ); } }
如果需要动态设置message,可以让控制器返回包含message和data的对象,然后修改拦截器的map逻辑:
map((response) => ({ status: 'success', code: 200, message: response.message || '请求成功', data: response.data || response, request: requestInfo, })),
二、实现全局异常过滤器
异常过滤器捕获所有未处理的异常,统一包装成你需要的异常响应格式。创建AllExceptionsFilter:
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common'; import { Request, Response } from 'express'; @Catch() // 捕获所有类型的异常 export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); // 区分HTTP异常和未知异常 const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; const message = exception instanceof HttpException ? (exception.getResponse() as any).message || exception.message : '服务器内部错误'; const error = exception instanceof HttpException ? exception.getResponse() || exception : exception; // 返回统一格式的异常响应 response.status(status).json({ status: 'error', code: status, // 可替换为自定义业务错误码 message: message, error: error, request: { url: request.url, method: request.method, }, }); } }
三、全局注册拦截器和过滤器
有两种方式可以全局注册,任选其一即可:
方式1:在main.ts中直接注册
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { TransformInterceptor } from './interceptors/transform.interceptor'; import { AllExceptionsFilter } from './filters/all-exceptions.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); // 注册全局拦截器和异常过滤器 app.useGlobalInterceptors(new TransformInterceptor()); app.useGlobalFilters(new AllExceptionsFilter()); await app.listen(3000); } bootstrap();
方式2:在模块中通过依赖注入注册
适合需要注入其他服务到拦截器/过滤器的场景,以AppModule为例:
import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR, APP_FILTER } from '@nestjs/core'; import { TransformInterceptor } from './interceptors/transform.interceptor'; import { AllExceptionsFilter } from './filters/all-exceptions.filter'; @Module({ providers: [ { provide: APP_INTERCEPTOR, useClass: TransformInterceptor, }, { provide: APP_FILTER, useClass: AllExceptionsFilter, }, ], }) export class AppModule {}
四、自定义扩展说明
- 业务码替换:可以将
code字段替换为你的自定义业务状态码,比如在异常过滤器中读取自定义异常的业务码,或者在拦截器中根据业务场景设置不同的成功码。 - 异常细分处理:如果需要针对特定类型的异常(比如自定义业务异常)做特殊处理,可以在
AllExceptionsFilter中添加条件判断,单独处理该异常的code和message。
内容的提问来源于stack exchange,提问作者Pandhu
相关产品推荐
相关产品推荐

