Spring RestTemplate:配置类中重写ResponseErrorHandler不生效
我来帮你梳理下可能导致自定义错误处理器没生效的常见原因,咱们逐一排查:
确认配置类被Spring正确扫描
首先要保证你的配置类上标注了@Configuration注解,并且这个类所在的包在Spring的扫描范围内(比如Spring Boot主启动类的@SpringBootApplication默认扫描同包及子包)。如果配置类不在默认扫描路径,需要在主启动类上添加@ComponentScan指定额外的扫描包路径。检查RestTemplate的注入方式
业务代码中使用RestTemplate时,一定要通过@Autowired或@Resource从Spring容器中获取实例,绝对不能手动new RestTemplate——否则拿到的是全新的、未配置自定义错误处理器的实例。完善
hasError方法的判断逻辑
你贴的代码里hasError方法不完整,这个方法是Spring判断是否需要触发错误处理的关键:如果它返回false,handleError方法根本不会执行。
参考默认实现的逻辑,正确的错误判断应该覆盖4xx和5xx状态码,示例如下:@Override public boolean hasError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = response.getStatusCode(); return statusCode.is4xxClientError() || statusCode.is5xxServerError(); }确保
handleError方法有可观测的处理逻辑
就算hasError返回true,如果handleError里没有任何可观测的操作(比如日志、抛异常),你可能会误以为处理器没生效。建议在方法中添加明确的处理逻辑,比如:private static final Logger log = LoggerFactory.getLogger(RsponseError.class); @Override public void handleError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = response.getStatusCode(); String responseBody = new String(response.getBody().readAllBytes(), StandardCharsets.UTF_8); if (statusCode.is4xxClientError()) { log.error("客户端错误响应,状态码:{},响应体:{}", statusCode, responseBody); throw new RuntimeException("客户端请求错误:" + statusCode); } else if (statusCode.is5xxServerError()) { log.error("服务端错误响应,状态码:{},响应体:{}", statusCode, responseBody); throw new RuntimeException("服务端处理错误:" + statusCode); } }排查是否存在多个RestTemplate Bean
如果Spring容器中存在多个RestTemplate实例,注入时可能误拿到了未配置错误处理器的那个。可以给你的自定义RestTemplate Bean指定名称,然后注入时明确指定:@Bean("customRestTemplate") public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory())); restTemplate.setErrorHandler(new RsponseError()); return restTemplate; }注入时:
@Autowired @Qualifier("customRestTemplate") private RestTemplate restTemplate;验证测试请求确实返回错误状态码
最后确认你测试的请求是否真的返回了4xx或5xx的状态码。如果请求返回200等成功状态码,hasError会返回false,处理器自然不会触发。可以先用Postman等工具验证接口的响应状态,再测试代码。
内容的提问来源于stack exchange,提问作者Bento

