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

如何基于响应对象而非状态码,用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:47:43