Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
spring-retry-toolkit — 针对 CVE-2026-41710 的 spring retry 1.3.x 修复专用小众工具包 | Kitploit
工具/GitHubGitHub/nichetoolkit/spring-retry-toolkit
漏洞分析Web安全供应链安全
GitHubnichetoolkit/spring-retry-toolkit

spring-retry-toolkit

针对 CVE-2026-41710 的 spring retry 1.3.x 修复专用小众工具包

查看仓库
212个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Javadocs

本项目为 Spring 应用提供声明式重试支持。它被用于 Spring Batch、Spring Integration 及其他项目中。 同时也支持命令式重试,以便显式使用。

版本

该版本将 spring-retry 修复为 2.0.13,适用于 java8 以及 spring4 或 spring5, 更多信息请参考官方 Spring 2.0.13 版本

快速开始

本节简要介绍如何开始使用 Spring Retry。 其中包含一个声明式示例和一个命令式示例。

声明式示例

以下示例展示了如何以声明式风格使用 Spring Retry:

@Configuration
@EnableRetry
public class Application {

    @Bean
    public Service service() {
        return new Service();
    }

}

@Service
class Service {
    @Retryable(RemoteAccessException.class)
    public void service() {
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e) {
       // ... panic
    }
}

此示例调用 service 方法,如果该方法因 RemoteAccessException 而失败,则进行重试(默认最多重试三次),如果仍然失败,则尝试调用 recover 方法。 @Retryable 注解属性中提供了多种选项,用于包含和排除异常类型、限制重试次数以及设置退避策略。

前面展示的使用 @Retryable 注解以声明式方式应用重试处理的方法,会对 AOP 类产生额外的运行时依赖。有关如何在项目中解决此依赖的详细信息,请参阅 'Java Configuration for Retry Proxies' 部分。

命令式示例

以下示例展示了如何以命令式风格使用 Spring Retry(自 1.3 版本起可用):

RetryTemplate template = RetryTemplate.builder()
				.maxAttempts(3)
				.fixedBackoff(1000)
				.retryOn(RemoteAccessException.class)
				.build();

template.execute(ctx -> {
    // ... do something
});

对于 1.3 之前的版本, 请参阅 RetryTemplate 部分中的示例。

构建

Spring Retry 需要 Java 1.7 和 Maven 3.0.5(或更高版本)。 要构建,请运行以下 Maven 命令:

$ mvn install

功能与 API

本节讨论 Spring Retry 的功能,并展示如何使用其 API。

使用 RetryTemplate

为了使处理更加健壮并减少失败的可能性,有时自动重试失败的操作会有所帮助,以防它在后续尝试中可能成功。容易受到此类处理的错误本质上是暂时性的。例如,由于网络故障而失败的远程 Web 服务或 RMI 服务调用,或数据库更新中的 DeadLockLoserException,可能在短暂等待后自行解决。为了自动化此类操作的重试,Spring Retry 提供了 RetryOperations 策略。RetryOperations 接口定义如下:

public interface RetryOperations {

    <T> T execute(RetryCallback<T> retryCallback) throws Exception;

    <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
        throws Exception;

    <T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
        throws Exception, ExhaustedRetryException;

    <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
        RetryState retryState) throws Exception;

}

基础回调是一个简单的接口,允许你插入一些需要重试的业务逻辑:

public interface RetryCallback<T> {

    T doWithRetry(RetryContext context) throws Throwable;

}

回调会被尝试执行,如果失败(抛出 Exception),则会重试,直到成功或实现决定中止。RetryOperations 接口中有多个重载的 execute 方法,用于处理所有重试尝试耗尽后的各种恢复用例,以及处理重试状态,这使客户端和实现能够在调用之间存储信息(稍后会详细介绍)。

RetryOperations 最简单的通用实现是 RetryTemplate。以下示例展示了如何使用它:

RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback<Foo>() {

    public Foo doWithRetry(RetryContext context) {
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

在前面的示例中,我们执行一次 Web 服务调用并将结果返回给用户。 如果该调用失败,则会重试,直到达到超时时间。

从 1.3 版本开始,还提供了 RetryTemplate 的流式配置,如下所示:

RetryTemplate.builder()
      .maxAttempts(10)
      .exponentialBackoff(100, 2, 10000)
      .retryOn(IOException.class)
      .traversingCauses()
      .build();

RetryTemplate.builder()
      .fixedBackoff(10)
      .withinMillis(3000)
      .build();

RetryTemplate.builder()
      .infiniteRetry()
      .retryOn(IOException.class)
      .uniformRandomBackoff(1000, 3000)
      .build();

使用 RetryContext

RetryCallback 的方法参数是一个 RetryContext。许多回调会忽略该上下文。然而,如有必要,你可以将其用作属性包,以便在迭代期间存储数据。

如果在同一线程中存在正在进行的嵌套重试,则 RetryContext 会有一个父上下文。父上下文有时可用于存储需要在多次 execute 调用之间共享的数据。

使用 RecoveryCallback

当重试耗尽时,RetryOperations 可以将控制权传递给另一个回调:RecoveryCallback。要使用此功能,客户端可以将这些回调一起传递给同一个方法,如下例所示:

Foo foo = template.execute(new RetryCallback<Foo>() {
    public Foo doWithRetry(RetryContext context) {
        // business logic here
    },
  new RecoveryCallback<Foo>() {
    Foo recover(RetryContext context) throws Exception {
          // recover logic here
    }
});

如果业务逻辑在模板决定中止之前未能成功,客户端有机会通过恢复回调执行一些替代处理。

无状态重试

在最简单的情况下,重试只是一个 while 循环:RetryTemplate 可以持续尝试,直到成功或失败。RetryContext 包含一些状态,用于决定是重试还是中止。然而,这个状态位于栈上,无需将其存储在任何全局位置。因此,我们称之为“无状态重试”。无状态重试与有状态重试的区别体现在 RetryPolicy 的实现中(RetryTemplate 可以处理两者)。在无状态重试中,回调始终在与重试失败时相同的线程中执行。

有状态重试

当失败导致事务性资源变为无效时,有一些特殊的考虑。这不适用于简单的远程调用,因为(通常)没有事务性资源,但它有时适用于数据库更新,尤其是在使用 Hibernate 时。在这种情况下,立即重新抛出导致失败的异常才有意义,这样事务可以回滚,我们可以开始一个新的(且有效的)事务。

在这些情况下,无状态重试不够好,因为重新抛出和回滚必然涉及离开 RetryOperations.execute() 方法,并可能丢失栈上的上下文。为了避免丢失上下文,我们必须引入一种存储策略,将其从栈上提升出来并(至少)放入堆存储中。为此,Spring Retry 提供了一种名为 RetryContextCache 的存储策略,你可以将其注入到 RetryTemplate 中。RetryContextCache 的默认实现是内存中的,使用一个简单的 Map。它具有严格强制实施的最大容量,以避免内存泄漏,但它没有任何高级缓存特性(例如生存时间)。如果你需要这些特性,应考虑注入一个具有这些特性的 Map。对于集群环境中多进程的高级用法,你可能还需要考虑用某种集群缓存来实现 RetryContextCache(不过,即使在集群环境中,这也可能有些过度)。

RetryOperations 的部分职责是在失败的操作以新的执行(通常包装在新事务中)返回时识别它们。为便于此,Spring Retry 提供了 RetryState 抽象。它与 RetryOperations 中的特殊 execute 方法配合使用。

失败的操作通过跨多次重试调用识别状态来识别。要识别状态,你可以提供一个 RetryState 对象,它负责返回标识该项的唯一键。该标识符用作 RetryContextCache 中的键。

警告: 在 RetryState 返回的键中实现 Object.equals() 和 Object.hashCode() 时要非常小心。最好的建议是使用业务键来标识项。对于 JMS 消息,你可以使用消息 ID。

当重试耗尽时,你还可以选择以不同的方式处理失败的项,而不是调用 RetryCallback(现在推测它很可能失败)。与无状态情况一样,此选项由 RecoveryCallback 提供,你可以通过将其传递给 RetryOperations 的 execute 方法来提供。

是否重试的决定实际上委托给常规的 RetryPolicy,因此关于限制和超时的常见关注点可以注入到那里(参见 Additional Dependencies 部分)。

重试策略

在 RetryTemplate 内部,execute 方法中决定重试还是失败由 RetryPolicy 决定,它同时也是 RetryContext 的工厂。RetryTemplate 负责使用当前策略创建 RetryContext,并在每次尝试时将其传递给 RetryCallback。回调失败后,RetryTemplate 必须调用 RetryPolicy,要求其更新状态(状态存储在 RetryContext 中)。然后它询问策略是否可以再进行一次尝试。如果无法再进行尝试(例如,因为已达到限制或检测到超时),策略还负责识别耗尽状态——但不负责处理异常。RetryTemplate 抛出原始异常,除非在有状态且无可用恢复的情况下。在这种情况下,它会抛出 RetryExhaustedException。你也可以在 RetryTemplate 中设置一个标志,使其无条件抛出回调(即用户代码)中的原始异常。

提示: 失败本质上要么可重试,要么不可重试——如果业务逻辑总是抛出相同的异常,重试它也无济于事。因此,你不应针对所有异常类型进行重试。相反,应尽量只关注那些你预期可重试的异常。更激进地重试通常不会对业务逻辑造成危害,但这样做是浪费的,因为如果失败是确定性的,那么就是在浪费时间重试你事先已知是致命的事情。

Spring Retry 提供了一些简单的通用无状态 RetryPolicy 实现(例如 SimpleRetryPolicy)以及前面示例中使用的 TimeoutRetryPolicy。

SimpleRetryPolicy 允许对指定的异常类型列表中的任何异常进行重试,最多重试固定次数。以下示例展示了如何使用它:

// Set the max attempts including the initial attempt before retrying
// and retry on all exceptions (this is the default):
SimpleRetryPolicy policy = new SimpleRetryPolicy(5, Collections.singletonMap(Exception.class, true));

// Use the policy...
RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(policy);
template.execute(new RetryCallback<Foo>() {
    public Foo doWithRetry(RetryContext context) {
        // business logic here
    }
});

还有一个更灵活的实现,称为 ExceptionClassifierRetryPolicy。 它允许你通过 ExceptionClassifier 抽象为任意一组异常类型配置不同的重试行为。该策略的工作方式是调用分类器将异常转换为委托 RetryPolicy。例如,可以将一种异常类型映射到不同的策略,从而使其在失败前比另一种异常类型重试更多次。

你可能需要实现自己的重试策略以实现更定制化的决策。例如,当存在一种众所周知的、特定于解决方案的异常分类,将异常分为可重试和不可重试时。

退避策略

在瞬时故障后重试时,通常有助于在再次尝试之前等待一段时间,因为(通常)故障是由某些只能通过等待才能解决的问题引起的。如果 RetryCallback 失败,RetryTemplate 可以根据 BackoffPolicy 暂停执行。以下清单展示了 BackoffPolicy 接口的定义:

public interface BackoffPolicy {

    BackOffContext start(RetryContext context);

    void backOff(BackOffContext backOffContext)
        throws BackOffInterruptedException;

}

BackoffPolicy 可以自由选择任何方式来实现退避。Spring Retry 提供的策略都使用 Object.wait()。一个常见的用例是采用指数级递增的等待时间进行退避,以避免两次重试进入同步状态并同时失败(这是从以太网中学到的教训)。为此,Spring Retry 提供了 ExponentialBackoffPolicy。Spring Retry 还提供了随机化的延迟策略,这些策略在复杂系统中避免相关故障之间产生共振时非常有用。

监听器

在多次不同的重试过程中,能够接收针对横切关注点的额外回调通常很有用。为此,Spring Retry 提供了 RetryListener 接口。RetryTemplate 允许你注册 RetryListener 实例,它们会收到带有 RetryContext 和 Throwable 的回调(在迭代过程中可用时)。

以下清单展示了 RetryListener 接口:

public interface RetryListener {
下载工具