SpringBoot技术实践-SpringRetry重试框架,查缺补漏

本文介绍了SpringBoot中SpringRetry的使用,通过@Controller和@Retryable注解展示了如何实现接口重试,详细配置了初始延迟和重试次数。文章末尾作者分享了帮助求职者节省时间的心得,并提供了相关的学习资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

}

}




1.  在controller中注入RetryTemplate使用,也可以是在service中



@RestController

public class SpringRetryController {

@Resource

private RetryTemplate retryTemplate;

private static int count = 0;



@RequestMapping("/retry")

public Object retry() {

    try {

        count = 0;

        retryTemplate.execute((RetryCallback<Void, RuntimeException>) context -> {

            // 业务代码

            // ....

            // 模拟抛出异常

            ++count;

            throw new RuntimeException("抛出异常");

        });

    } catch (RuntimeException e) {

        System.out.println("Exception");

    }



    return "retry = " + count;

}

}




1.  访问retry接口,然后观察日志输出



18:27:20.648 - http-nio-8888-exec-1 - open

18:27:20.649 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:20.649 - http-nio-8888-exec-1 - onError

18:27:21.658 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:21.658 - http-nio-8888-exec-1 - onError

18:27:23.670 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:23.670 - http-nio-8888-exec-1 - onError

18:27:27.679 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:27.679 - http-nio-8888-exec-1 - onError

18:27:35.681 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:35.681 - http-nio-8888-exec-1 - onError

18:27:35.681 - http-nio-8888-exec-1 - close




[](https://gitee.com/vip204888/java-p7)三、EnableRetry

================================================================================



1.  @EnableRetry开启重试,在类上指定的时候方法将默认执行,重试三次

2.  定义service,开启@EnableRetry注解和指定@Retryable,重试可以参考后面一节



import org.springframework.retry.annotation.Retryable;

public interface RetryService {

/**

 * 重试方法调用

 */

@Retryable

void retryServiceCall();

}


import org.springframework.retry.annotation.EnableRetry;

import org.springframework.stereotype.Service;



@EnableRetry

@Service

public class RetryServiceImpl implements RetryService {



    @Override

    public void retryServiceCall() {

        PrintUtil.print("方法调用..");

        throw new RuntimeException("手工异常");

    }

} 

```



1.  controller中注入service



```

@RequestMapping("/retryAnnotation")

public Object retryAnnotation() {

    retryService.retryServiceCall();

    return "retryAnnotation";

} 

```



1.  将会默认重试



```

18:46:48.721 - http-nio-8888-exec-1 - 方法调用..

18:46:49.724 - http-nio-8888-exec-1 - 方法调用..

18:46:50.730 - http-nio-8888-exec-1 - 方法调用..

java.lang.RuntimeException: 手工异常 

```



[](https://gitee.com/vip204888/java-p7)四、Retryable

==============================================================================



1.  用于需要重试的方法上的注解

2.  有以下几个属性

    *   Retryable注解参数

        *   value:指定发生的异常进行重试

        *   include:和value一样,默认空,当exclude也为空时,所有异常都重试

        *   exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试

        *   maxAttemps:重试次数,默认3

        *   backoff:重试补偿机制,默认没有

    *   @Backoff 注解 重试补偿策略

        *   不设置参数时,默认使用FixedBackOffPolicy(指定等待时间),重试等待1000ms

        *   设置delay,使用FixedBackOffPolicy(指定等待设置delay和maxDealy时,重试等待在这两个值之间均态分布)

        *   设置delay、maxDealy、multiplier,使用 ExponentialBackOffPolicy(指数级重试间隔的实现),multiplier即指定延迟倍数,比如delay=5000L,multiplier=2,则第一次重试为5秒,第二次为10秒,第三次为20秒



```

@Target({ ElementType.METHOD, ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Retryable {



	/**

	 * Retry interceptor bean name to be applied for retryable method. Is mutually

	 * exclusive with other attributes.

	 * @return the retry interceptor bean name

	 */

	String interceptor() default "";



	/**

	 * Exception types that are retryable. Synonym for includes(). Defaults to empty (and

	 * if excludes is also empty all exceptions are retried).

	 * @return exception types to retry

	 */

	Class<? extends Throwable>[] value() default {};



	/**

	 * Exception types that are retryable. Defaults to empty (and if excludes is also

	 * empty all exceptions are retried).

	 * @return exception types to retry

	 */

	Class<? extends Throwable>[] include() default {};



	/**

	 * Exception types that are not retryable. Defaults to empty (and if includes is also

	 * empty all exceptions are retried).

	 * If includes is empty but excludes is not, all not excluded exceptions are retried

	 * @return exception types not to retry

	 */

	Class<? extends Throwable>[] exclude() default {};



	/**

	 * A unique label for statistics reporting. If not provided the caller may choose to

	 * ignore it, or provide a default.

	 *

	 * @return the label for the statistics

	 */

	String label() default "";



	/**

	 * Flag to say that the retry is stateful: i.e. exceptions are re-thrown, but the

	 * retry policy is applied with the same policy to subsequent invocations with the

	 * same arguments. If false then retryable exceptions are not re-thrown.

	 * @return true if retry is stateful, default false

	 */

	boolean stateful() default false;



	/**

	 * @return the maximum number of attempts (including the first failure), defaults to 3

	 */

	int maxAttempts() default 3;



	/**

	 * @return an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3

	 * Overrides {@link #maxAttempts()}.

	 * @date 1.2

	 */

	String maxAttemptsExpression() default "";



	/**

	 * Specify the backoff properties for retrying this operation. The default is a

	 * simple {@link Backoff} specification with no properties - see it's documentation

	 * for defaults.

	 * @return a backoff specification

	 */

	Backoff backoff() default @Backoff();



	/**

	 * Specify an expression to be evaluated after the {@code SimpleRetryPolicy.canRetry()}

	 * returns true - can be used to conditionally suppress the retry. Only invoked after

	 * an exception is thrown. The root object for the evaluation is the last {@code Throwable}.

	 * Other beans in the context can be referenced.

	 * For example:

	 * <pre class=code>

	 *  {@code "message.contains('you can retry this')"}.

	 * </pre>

	 * and

	 * <pre class=code>

	 *  {@code "@someBean.shouldRetry(#root)"}.

	 * </pre>

	 * @return the expression.

	 * @date 1.2

	 */

	String exceptionExpression() default "";



	/**

	 * Bean names of retry listeners to use instead of default ones defined in Spring context

	 * @return retry listeners bean names

	 */

	String[] listeners() default {};



} 

```



1.  在需要重试的方法上配置对应的重试次数、重试异常的异常类型、设置回退延迟时间、重试策略、方法监听名称



```

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Backoff {



	/**

	 * Synonym for {@link #delay()}.

	 *

	 * @return the delay in milliseconds (default 1000)

	 */

	long value() default 1000;



	/**

	 * A canonical backoff period. Used as an initial value in the exponential case, and

	 * as a minimum value in the uniform case.

	 * @return the initial or canonical backoff period in milliseconds (default 1000)

	 */

	long delay() default 0;



	/**

	 * The maximimum wait (in milliseconds) between retries. If less than the

	 * {@link #delay()} then the default of

	 * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL}

	 * is applied.

	 *

	 * @return the maximum delay between retries (default 0 = ignored)

	 */

	long maxDelay() default 0;



	/**

	 * If positive, then used as a multiplier for generating the next delay for backoff.

	 *

	 * @return a multiplier to use to calculate the next backoff delay (default 0 =

	 * ignored)

	 */

	double multiplier() default 0;



	/**

	 * An expression evaluating to the canonical backoff period. Used as an initial value

	 * in the exponential case, and as a minimum value in the uniform case. Overrides

	 * {@link #delay()}.

	 * @return the initial or canonical backoff period in milliseconds.

	 * @date 1.2

	 */

	String delayExpression() default "";



	/**

	 * An expression evaluating to the maximimum wait (in milliseconds) between retries.

	 * If less than the {@link #delay()} then the default of

	 * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL}

	 * is applied. Overrides {@link #maxDelay()}

	 *

	 * @return the maximum delay between retries (default 0 = ignored)

	 * @date 1.2

	 */

	String maxDelayExpression() default "";



	/**

	 * Evaluates to a vaule used as a multiplier for generating the next delay for

	 * backoff. Overrides {@link #multiplier()}.

	 *

	 * @return a multiplier expression to use to calculate the next backoff delay (default

	 * 0 = ignored)

	 * @date 1.2

	 */

	String multiplierExpression() default "";



	/**

	 * In the exponential case ({@link #multiplier()} &gt; 0) set this to true to have the

	 * backoff delays randomized, so that the maximum delay is multiplier times the

	 * previous delay and the distribution is uniform between the two values.

	 *

	 * @return the flag to signal randomization is required (default false)

	 */

	boolean random() default false;



} 

@Component

public class PlatformClassService {

@Retryable(

    // 重试异常的异常类型

    value = {Exception.class},

    // 最大重试次数

    maxAttempts = 5,

    // 设置回退延迟时间

    backoff = @Backoff(delay = 500),

    // 配置回调方法名称

    listeners = "retryListener"

)

public void call() {

    System.out.println("call...");

    throw new RuntimeException("手工异常");

}

}

// 初始延迟2秒,然后之后验收1.5倍延迟重试,总重试次数4

@Retryable(value = {Exception.class}, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 1.5))




1.  监听方法,在配置类中进行配置



/**

  • 注解调用

*/

@Bean

public RetryListener retryListener() {

return new RetryListener() {

    @Override

    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {

写在最后

可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。

复习一周,字节跳动三场技术面+HR面,不小心拿了offer

复习一周,字节跳动三场技术面+HR面,不小心拿了offer

上面的这些(算法与数据结构)+(Java多线程学习手册)+(计算机网络顶级教程)等学习资源我都在这里公开分享出来

以上我的经历希望能够给大家带来帮助,需要这些资料的朋友可以戳这里,就可以免费拿到了

(delay = 2000L, multiplier = 1.5))




1.  监听方法,在配置类中进行配置



/**

  • 注解调用

*/

@Bean

public RetryListener retryListener() {

return new RetryListener() {

    @Override

    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {

写在最后

可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。

[外链图片转存中…(img-A2VI3rd4-1628419227218)]

[外链图片转存中…(img-gijxIysa-1628419227220)]

上面的这些(算法与数据结构)+(Java多线程学习手册)+(计算机网络顶级教程)等学习资源我都在这里公开分享出来

以上我的经历希望能够给大家带来帮助,需要这些资料的朋友可以戳这里,就可以免费拿到了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值