如何基于响应对象而非状态码,用Spring Retry重试REST端点?
解决方案
要实现基于Job状态的重试逻辑,需调整现有代码的异常触发机制与重试策略匹配,具体步骤如下:
1. 修正自定义异常类型
Spring Retry默认仅对RuntimeException触发重试,因此需要让自定义异常继承RuntimeException(同时重命名类名以贴合语义):
public class RetryableJobStatusException extends RuntimeException { public RetryableJobStatusException(String message) { super(message); } }
2. 修改API调用方法,触发重试条件
在makeApiCall中判断返回的status:
- 若为
creating/queued/running,抛出RetryableJobStatusException触发重试 - 若为
success/failed/skipped/killed,直接返回状态值终止重试
修改后的代码:
private String makeApiCall(String jobId) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders httpHeaders = new HttpHeaders(); List<MediaType> acceptType = new ArrayList<>(); acceptType.add(MediaType.APPLICATION_JSON); httpHeaders.setAccept(acceptType); httpHeaders.setContentType(MediaType.APPLICATION_JSON); // 确保requestEntity和params已完成初始化 ResponseEntity<String> response = restTemplate.exchange(apiEndpoint, HttpMethod.GET, requestEntity, String.class, params); ObjectMapper objectMapper = new ObjectMapper(); JobStatus jobStatus; try { jobStatus = objectMapper.readValue(response.getBody(), JobStatus.class); } catch (JsonProcessingException e) { throw new RuntimeException("解析Job状态响应失败", e); } String status = jobStatus.getStatus(); // 判断需要重试的状态 if (Arrays.asList("creating", "queued", "running").contains(status.toLowerCase())) { throw new RetryableJobStatusException("Job仍处于" + status + "状态,将重试"); } // 非重试状态直接返回 return status; }
3. 调整RetryTemplate执行逻辑
无需返回null,直接通过异常触发重试;当方法正常返回时,即可拿到最终状态:
public ResponseEntity<String> jobStatusCheck(String jobId) { RetryTemplate retry = new RetryTemplate(); FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(10000); // 10秒重试间隔 retry.setRetryPolicy(new JobStatusRetryPolicy()); retry.setBackOffPolicy(backOffPolicy); try { String finalStatus = retry.execute(context -> makeApiCall(jobId)); return ResponseEntity.ok(finalStatus); } catch (Exception e) { throw new RuntimeException("Job状态检查重试过程中出错", e); } }
4. 更新重试策略类
匹配新的自定义异常,确保仅在需要重试的场景下执行重试:
public class JobStatusRetryPolicy extends ExceptionClassifierRetryPolicy { public JobStatusRetryPolicy() { SimpleRetryPolicy retryOnRetryableStatus = new SimpleRetryPolicy(); retryOnRetryableStatus.setMaxAttempts(3); // 最多执行3次调用(首次调用+2次重试) this.setExceptionClassifier(classifiable -> { // 仅遇到重试状态异常时执行重试 if (classifiable instanceof RetryableJobStatusException) { return retryOnRetryableStatus; } // 其他异常或成功场景,终止重试 return new NeverRetryPolicy(); }); } }
核心逻辑说明
- 重试触发:仅当API返回需要等待的状态时,抛出特定异常,Spring Retry才会启动重试流程
- 终止条件:当API返回
success/failed等最终状态时,方法正常返回,RetryTemplate终止重试并返回结果 - 重试次数:
setMaxAttempts(3)表示最多执行3次调用(包含首次请求)
内容的提问来源于stack exchange,提问作者Pranaya Behera
相关产品推荐
相关产品推荐

