咨询基于返回结果的方法重试方案(最多4次,不依赖@Retryable)
基于返回值的重试实现方案
针对你需要在OperationResponse的done字段为false时重试最多4次的需求,这里提供几个实用的实现方案:
方案一:手动实现重试逻辑
这是最直接的方式,不需要引入任何额外依赖,完全自己控制重试流程。
public OperationResponse getOperationResponseWithRetry(YaRequest request) { final int MAX_RETRIES = 4; OperationResponse response; for (int i = 0; i <= MAX_RETRIES; i++) { response = getOperationResponse(request); if (response.done) { return response; } // 可选:添加重试间隔,避免频繁调用服务 try { Thread.sleep(1000); // 间隔1秒,可根据业务调整 } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("重试被中断", e); } } // 重试耗尽后返回最后一次的响应,也可以根据业务抛出自定义异常 return getOperationResponse(request); }
优点:轻量、无依赖,重试逻辑完全可控;缺点:代码冗余,如果多个方法需要重试,会重复写循环逻辑。
方案二:扩展Spring Retry实现返回值驱动重试
如果你的项目已经在使用Spring生态,可以通过自定义RetryPolicy来实现基于返回值的重试,不用依赖异常触发。
首先配置RetryTemplate:
@Configuration public class RetryConfig { @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); // 最多重试4次(包含首次调用,共5次尝试) SimpleRetryPolicy countRetryPolicy = new SimpleRetryPolicy(); countRetryPolicy.setMaxAttempts(5); // 自定义重试触发条件:返回的done为false时允许重试 RetryPolicy resultBasedRetryPolicy = new RetryPolicy() { @Override public boolean canRetry(RetryContext context) { OperationResponse response = (OperationResponse) context.getAttribute("response"); return response != null && !response.done; } @Override public RetryContext open(RetryContext parent) { return new DefaultRetryContext(parent); } @Override public void close(RetryContext context) {} @Override public void registerThrowable(RetryContext context, Throwable throwable) {} }; // 组合策略:同时满足次数限制和返回值条件才重试 CompositeRetryPolicy compositePolicy = new CompositeRetryPolicy(); compositePolicy.setPolicies(new RetryPolicy[]{countRetryPolicy, resultBasedRetryPolicy}); retryTemplate.setRetryPolicy(compositePolicy); // 可选:添加固定间隔退避策略 FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(1000); retryTemplate.setBackOffPolicy(backOffPolicy); return retryTemplate; } }
然后用RetryTemplate调用目标方法:
@Autowired private RetryTemplate retryTemplate; public OperationResponse getOperationResponseWithSpringRetry(YaRequest request) { return retryTemplate.execute(context -> { OperationResponse response = getOperationResponse(request); context.setAttribute("response", response); return response; }); }
优点:复用Spring生态的重试能力,支持多种退避策略(指数退避、随机退避等),代码复用性好;缺点:依赖Spring环境,配置相对复杂一点。
方案三:使用Guava Retryer实现灵活重试
Guava提供了专门的Retryer工具类,可以灵活配置重试条件、次数、间隔等,适合非Spring项目或者需要更灵活重试规则的场景。
先引入Guava依赖(Maven示例):
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>32.1.3-jre</version> <!-- 使用最新稳定版本 --> </dependency>
然后实现重试逻辑:
import com.google.common.util.concurrent.Retryer; import com.google.common.util.concurrent.RetryerBuilder; import com.google.common.util.concurrent.StopStrategies; import com.google.common.util.concurrent.WaitStrategies; import java.util.concurrent.TimeUnit; public OperationResponse getOperationResponseWithGuavaRetry(YaRequest request) { Retryer<OperationResponse> retryer = RetryerBuilder.<OperationResponse>newBuilder() // 指定重试触发条件:done为false时重试 .retryIfResult(response -> !response.done) // 最多重试4次(总尝试5次) .withStopStrategy(StopStrategies.stopAfterAttempt(5)) // 每次重试间隔1秒 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) .build(); try { return retryer.call(() -> getOperationResponse(request)); } catch (Exception e) { // 重试耗尽或调用出错时抛出异常,也可以返回默认响应 throw new RuntimeException("重试次数耗尽,未获取到完成状态的响应", e); } }
优点:配置灵活,支持多种重试策略,无需依赖Spring;缺点:需要引入Guava依赖。
内容的提问来源于stack exchange,提问作者NeverSleeps
相关产品推荐
相关产品推荐

