You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Interceptor时@ControllerAdvice异常处理Postman返回空

问题场景

项目集成Spring MVC的Interceptor拦截器时,全局异常处理的日志仅能在终端控制台正常输出,预期需要将异常信息同步返回给REST API调用端,但实际通过Postman调用对应接口时响应体为空,无任何异常返回内容。

相关代码

拦截器实现代码

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;


public class WebInterceptor implements HandlerInterceptor {
    
    private Logger logger = LoggerFactory.getLogger(WebInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception    {
        logger.error("WebInterceptor preHandle is now logged");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        logger.error("WebInterceptor posthandle is now logged");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.error("WebInterceptor afterCompletion is now logged");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
    
}

拦截器注册配置

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class AppConfig implements WebMvcConfigurer{

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new WebInterceptor()).addPathPatterns("/cart/**").order(1);
        registry.addInterceptor(new WebInterceptor()).addPathPatterns("/product/**").order(2);
    }
    
}

全局异常处理配置

import com.kongapigateway.KongAPIgateway.ModelException.DATE_FORMAT_ERROR;
import com.kongapigateway.KongAPIgateway.ModelException.ProductExecption;
import com.kongapigateway.KongAPIgateway.ModelException.ProductIDnotFound;
import com.kongapigateway.KongAPIgateway.ModelException.ProductValueNotNull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class WEbAspectExceptionConfig {
    
     private Logger logger = LoggerFactory.getLogger(WEbAspectExceptionConfig.class);

        @ExceptionHandler(ProductValueNotNull.class)
        @ResponseStatus
        public void handle(ProductValueNotNull e) {
            logger.error(e.getMessage());
        }
        
        @ExceptionHandler(DATE_FORMAT_ERROR.class)
        @ResponseStatus
        public void handle2(DATE_FORMAT_ERROR e) {
               logger.error(e.getMessage());
        }
        
        @ExceptionHandler(ProductExecption.class)
        @ResponseStatus
        public void handle2(ProductExecption e) {
               logger.error(e.getMessage());
        }
        
        @ExceptionHandler(ProductIDnotFound.class)
        @ResponseStatus
        public void handle2(ProductIDnotFound e) {
               logger.error(e.getMessage());
        }
}

现场现象

终端日志显示异常已经被全局异常处理器捕获,捕获到的异常提示为Please input all field,日志内容如下:

kongapigateway    | 2022-06-07 11:21:33.149  INFO 1 --- [nio-8095-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
kongapigateway    | 2022-06-07 11:21:33.161 ERROR 1 --- [nio-8095-exec-1] c.k.K.Interceptor.WebInterceptor         : WebInterceptor preHandle is now logged
kongapigateway    | 2022-06-07 11:21:33.277 ERROR 1 --- [nio-8095-exec-1] c.k.K.AOP.WEbAspectExceptionConfig       : Please input all field
kongapigateway    | 2022-06-07 11:21:33.277 ERROR 1 --- [nio-8095-exec-1] c.k.K.Interceptor.WebInterceptor         : WebInterceptor afterCompletion is now logged

通过Postman调用对应接口时,响应体完全为空,没有任何异常返回内容。

问题根因

全局异常处理类里所有@ExceptionHandler修饰的方法返回值都是void,方法内部仅做了日志打印,没有向HTTP响应体写入任何内容;同时@ResponseStatus注解没有指定对应的HTTP错误状态码,默认返回200状态码,Spring不会自动将异常信息序列化到响应中,最终调用方拿到空响应。

修复方法
  • 定义统一的错误响应结构,将所有异常处理方法的返回值改为该结构,方法内构造包含错误信息、错误码的响应对象返回。由于类上标注了@RestControllerAdvice,自带@ResponseBody序列化逻辑,返回的对象会自动转成JSON写入响应体。
  • 给@ResponseStatus注解指定匹配业务场景的HTTP状态码,比如参数校验错误对应HttpStatus.BAD_REQUEST(400),资源不存在对应HttpStatus.NOT_FOUND(404)。

修复后的异常处理代码示例:

import com.kongapigateway.KongAPIgateway.ModelException.DATE_FORMAT_ERROR;
import com.kongapigateway.KongAPIgateway.ModelException.ProductExecption;
import com.kongapigateway.KongAPIgateway.ModelException.ProductIDnotFound;
import com.kongapigateway.KongAPIgateway.ModelException.ProductValueNotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class WEbAspectExceptionConfig {
    
    private Logger logger = LoggerFactory.getLogger(WEbAspectExceptionConfig.class);

    @ExceptionHandler(ProductValueNotNull.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, Object> handle(ProductValueNotNull e) {
        logger.error(e.getMessage());
        Map<String, Object> res = new HashMap<>();
        res.put("code", 400);
        res.put("msg", e.getMessage());
        return res;
    }
        
    @ExceptionHandler(DATE_FORMAT_ERROR.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, Object> handleDateFormatError(DATE_FORMAT_ERROR e) {
        logger.error(e.getMessage());
        Map<String, Object> res = new HashMap<>();
        res.put("code", 400);
        res.put("msg", e.getMessage());
        return res;
    }
        
    @ExceptionHandler(ProductExecption.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Map<String, Object> handleProductError(ProductExecption e) {
        logger.error(e.getMessage());
        Map<String, Object> res = new HashMap<>();
        res.put("code", 500);
        res.put("msg", e.getMessage());
        return res;
    }
        
    @ExceptionHandler(ProductIDnotFound.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Map<String, Object> handleProductNotFound(ProductIDnotFound e) {
        logger.error(e.getMessage());
        Map<String, Object> res = new HashMap<>();
        res.put("code", 404);
        res.put("msg", e.getMessage());
        return res;
    }
}

注:可根据项目实际规范替换为项目统一的响应实体类,不用手写Map构造返回值。


内容的提问来源于stack exchange,提问作者SpicySandwich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 05:03:39