升级Spring Boot后,如何恢复1.5版本的默认异常映射?
刚升级完Spring Boot和Jersey就遇到异常响应格式变了?我太懂这种糟心的感觉了——Spring Boot 2.0确实调整了默认的错误输出结构,结合Jersey 2.26的升级,导致你原来1.5版本的熟悉格式不见了。下面给你两种靠谱的恢复方案:
解决方案一:自定义ErrorAttributes(全局生效)
Spring Boot 2.x用新的DefaultErrorAttributes实现替换了1.5版本的逻辑,我们可以通过继承它并重写方法,强制恢复旧的响应格式。
创建一个自定义的ErrorAttributes组件:
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.stereotype.Component; import org.springframework.web.context.request.WebRequest; import java.util.Map; @Component public class LegacyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { // 先获取默认的错误属性 Map<String, Object> attributes = super.getErrorAttributes(webRequest, includeStackTrace); // 调整为Spring Boot 1.5的字段结构(移除2.x新增字段并确保核心字段保留) attributes.remove("trace"); // 移除2.x新增的堆栈追踪字段,按需保留 // 确保必要字段都存在 attributes.putIfAbsent("timestamp", attributes.get("timestamp")); attributes.putIfAbsent("status", attributes.get("status")); attributes.putIfAbsent("error", attributes.get("error")); attributes.putIfAbsent("exception", attributes.get("exception")); attributes.putIfAbsent("message", attributes.get("message")); attributes.putIfAbsent("path", attributes.get("path")); return attributes; } }
这个组件会被Spring自动加载,全局覆盖默认的错误属性生成逻辑,不管是Jersey接口还是Spring MVC接口,都会返回1.5版本的格式。
解决方案二:适配Jersey的ExceptionMapper(针对Jersey接口)
如果你的Jersey接口异常被Jersey自身的处理机制接管,需要自定义ExceptionMapper,让它使用上面的LegacyErrorAttributes生成响应。
创建一个Jersey的异常映射器:
import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.WebRequest; import javax.inject.Inject; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import java.util.Map; @Provider public class LegacyJerseyExceptionMapper implements ExceptionMapper<Throwable> { private final ErrorAttributes errorAttributes; @Inject public LegacyJerseyExceptionMapper(ErrorAttributes errorAttributes) { this.errorAttributes = errorAttributes; } @Override public Response toResponse(Throwable throwable) { // 获取当前请求的WebRequest上下文 WebRequest webRequest = new ServletWebRequest( RequestContextHolder.getRequestAttributes().getRequest() ); // 用自定义的ErrorAttributes生成符合1.5格式的属性 Map<String, Object> errorAttributesMap = errorAttributes.getErrorAttributes(webRequest, false); // 确保异常类名和消息正确填充 errorAttributesMap.put("exception", throwable.getClass().getName()); errorAttributesMap.put("message", throwable.getMessage()); // 返回JSON格式的错误响应 return Response.status((Integer) errorAttributesMap.get("status")) .type(MediaType.APPLICATION_JSON_TYPE) .entity(errorAttributesMap) .build(); } }
记得把这个类注册到Jersey的配置里(比如在ResourceConfig的register方法中添加),这样Jersey处理未捕获异常时就会用我们的格式返回。
注意事项
- 如果你需要保留堆栈追踪,可以把
includeStackTrace参数设为true,1.5版本默认不返回该字段,按需调整即可 - 测试时直接抛出未处理异常(比如
IllegalStateException),对比响应结构是否和升级前一致 - 确保自定义组件被Spring或Jersey正确扫描到(比如
@Component和@Provider注解)
内容的提问来源于stack exchange,提问作者Czar
相关产品推荐
相关产品推荐

