自定义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; } }
额外优化建议
- 替换System.out.println:换成logger的debug/info级别输出,符合Spring项目的日志规范,方便线上排查问题
- 考虑使用更简洁的异常处理方式:如果你的项目是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序列化和响应头设置,出错概率更低。
- 检查Fault类的序列化能力:确保Fault类的字段有public的getter方法,或者用
@JsonProperty标注需要序列化的字段,否则ObjectMapper无法正确生成JSON内容,可能返回空对象。
内容的提问来源于stack exchange,提问作者sjain
相关产品推荐
相关产品推荐

