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

自定义Spring HandlerExceptionResolver无法写入JSON到HttpServletResponse

解决HandlerExceptionResolver无法写入JSON到HttpServletResponse的问题

我看了你的代码,遇到这个问题通常有几个容易忽略的细节,咱们一步步来排查和修复:

核心问题分析

你的逻辑方向是对的,但有几个小问题导致Spring可能覆盖了你写入的响应内容:

  • 返回null会让Spring认为你没处理完异常,它会继续调用默认的错误处理流程,直接覆盖掉你写入的JSON
  • 缺少字符编码设置,可能导致JSON内容编码异常,前端看不到正确结果
  • 没有确保Fault对象能被正确序列化(比如有没有提供public的getter方法?)

修复后的代码示例

public class CustomHandlerExceptionResolver implements org.springframework.web.servlet.HandlerExceptionResolver {
    protected final Log logger = LogFactory.getLog(this.getClass());
    @Override
    public ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
        logger.trace("-------------doResolveException-------------");
        
        if (exception instanceof HttpRequestMethodNotSupportedException) {
            Fault fault = new Fault();
            // 记得给Fault设置自定义错误信息,比如:
            // fault.setCode("METHOD_NOT_ALLOWED");
            // fault.setMessage("请求方法不允许,请使用POST方式调用");
            
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(Include.NON_NULL);
            
            try {
                // 先设置编码和响应类型,避免乱码
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=UTF-8");
                response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); // 用常量更规范
                
                String errorMessage = mapper.writeValueAsString(fault);
                PrintWriter writer = response.getWriter();
                writer.print(errorMessage);
                writer.flush();
                writer.close(); // 确保流被正确关闭
                
                // 返回空ModelAndView,告诉Spring我们已经处理完异常,不要走默认流程
                return new ModelAndView();
            } catch (IOException e) {
                logger.error("序列化异常信息失败", e);
                e.printStackTrace();
            }
        }
        
        // 非目标异常,返回null让Spring处理
        return null;
    }
}

额外优化建议

  1. 替换System.out.println:换成logger的debug/info级别输出,符合Spring项目的日志规范,方便线上排查问题
  2. 考虑使用更简洁的异常处理方式:如果你的项目是Spring MVC 3.2及以上版本,用@ControllerAdvice配合@ExceptionHandler会更省心,不需要手动操作response:
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<Fault> handleMethodNotAllowed(HttpRequestMethodNotSupportedException ex) {
        Fault fault = new Fault();
        fault.setMessage("请求方法不允许,支持的方法:" + Arrays.toString(ex.getSupportedHttpMethods()));
        return new ResponseEntity<>(fault, HttpStatus.METHOD_NOT_ALLOWED);
    }
}

这种方式Spring会自动帮你完成JSON序列化和响应头设置,出错概率更低。

  1. 检查Fault类的序列化能力:确保Fault类的字段有public的getter方法,或者用@JsonProperty标注需要序列化的字段,否则ObjectMapper无法正确生成JSON内容,可能返回空对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:01:49