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

如何在ControllerAdvice中获取Controller方法签名判断是否含@ResponseBody

结论

可以直接在@ExceptionHandler方法中获取到抛出异常的目标Controller方法的签名和注解信息。Spring MVC的异常处理方法支持自动注入HandlerMethod对象,该对象封装了目标请求处理方法的所有元数据,包含所属类信息、方法签名、方法及类上的注解等。

具体实现代码

你可以参考如下改造后的ControllerAdvice代码,实现你的需求:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import java.util.Map;

@ControllerAdvice
class SomeAdvice {

    // 去掉方法上的@ResponseBody注解,根据场景动态返回JSON或视图
    @ExceptionHandler(Exception.class)
    public Object handle(Exception e, HandlerMethod handlerMethod) {
        // 优先判断方法上是否标注@ResponseBody
        boolean returnJson = handlerMethod.hasMethodAnnotation(ResponseBody.class);
        // 方法上没有的话再判断Controller类上是否标注@ResponseBody(@RestController自带@ResponseBody,也会被识别)
        if (!returnJson) {
            returnJson = handlerMethod.getBeanType().isAnnotationPresent(ResponseBody.class);
        }

        if (returnJson) {
            // 接口类型的请求,返回指定格式的JSON响应
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(Map.of("message", "something happened"));
        } else {
            // 页面类型的请求,重定向到默认错误页面,也可直接返回视图名如"error"
            return "redirect:/error";
        }
    }
}

兼容边界场景

如果异常是在请求进入Controller方法前抛出的(比如路径不存在、过滤器/拦截器层面抛出异常),此时没有对应的HandlerMethod对象,会出现参数注入失败的问题,你可以调整参数做兼容:

@ExceptionHandler(Exception.class)
public Object handle(Exception e, Object handler) {
    if (handler instanceof HandlerMethod handlerMethod) {
        boolean returnJson = handlerMethod.hasMethodAnnotation(ResponseBody.class);
        if (!returnJson) {
            returnJson = handlerMethod.getBeanType().isAnnotationPresent(ResponseBody.class);
        }
        if (returnJson) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(Map.of("message", "something happened"));
        }
    }
    // 非Controller方法抛出的异常统一走错误页面
    return "redirect:/error";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:24:00