欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的接口重試機(jī)制解析

 更新時(shí)間:2024年01月24日 08:32:07   作者:北漂碼農(nóng)有話(huà)說(shuō)  
這篇文章主要介紹了Spring中的接口重試機(jī)制解析,大家在做項(xiàng)目的時(shí)候,往往會(huì)遇到一些接口由于網(wǎng)絡(luò)抖動(dòng)等問(wèn)題導(dǎo)致接口響應(yīng)超時(shí)等,這時(shí)候我們會(huì)希望能夠按照一定的規(guī)則進(jìn)行接口請(qǐng)求重試,需要的朋友可以參考下

背景

大家在做項(xiàng)目的時(shí)候,往往會(huì)遇到一些接口由于網(wǎng)絡(luò)抖動(dòng)等問(wèn)題導(dǎo)致接口響應(yīng)超時(shí)等,這時(shí)候我們會(huì)希望能夠按照一定的規(guī)則進(jìn)行接口 請(qǐng)求重試。

分析

一般情況下,以上描述的情況,我們可能需要后臺(tái)的定時(shí)任務(wù)去重新發(fā)起調(diào)用,以達(dá)到目的,這樣無(wú)疑會(huì)增加開(kāi)發(fā)成本,并且還得考慮 請(qǐng)求報(bào)文的保存等等問(wèn)題。

這時(shí)我們可以使用Spring提供的功能來(lái)完成這個(gè)需求。

實(shí)現(xiàn)

假設(shè)我們現(xiàn)在有一個(gè)接口,在這個(gè)接口流程中會(huì)出現(xiàn)一些異常,比如超時(shí)異常(數(shù)據(jù)庫(kù)的異常、遠(yuǎn)程調(diào)用的異常等),出現(xiàn)這樣的異常 我們就希望能夠自動(dòng)發(fā)起重新調(diào)用的功能。

創(chuàng)建工程

我們?yōu)榱藴y(cè)試方便就直接創(chuàng)建一個(gè)簡(jiǎn)單的Spring Boot的工程就可以了。創(chuàng)建的時(shí)候引入如下依賴(lài):

<dependency>
   <groupId>org.springframework.retry</groupId>
   <artifactId>spring-retry</artifactId>
</dependency>
<!--AOP依賴(lài)-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

說(shuō)明:由于Spring重試機(jī)制的基于注解的AOP實(shí)現(xiàn),所以我們需要映入AOP的依賴(lài),我們是Spring Boot項(xiàng)目直接使用AOP的啟動(dòng)器就可以了。

啟動(dòng)注解

由于我們是繼續(xù)Spring Boot來(lái)開(kāi)發(fā)這部分代碼,所以我們需要配置開(kāi)啟重試機(jī)制的的注解,代碼如下:

@SpringBootApplication
@EnableRetry
public class SpringbootApplication {
 public static void main(String[] args) {
  SpringApplication.run(SpringbootApplication.class, args);
 }
}

說(shuō)明:Spring重試機(jī)制主要是使用注解@Retryable來(lái)實(shí)現(xiàn)的

@Retryable

該注解的源碼如下:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {
    String recover() default "";
    String interceptor() default "";
    Class<? extends Throwable>[] value() default {};
    Class<? extends Throwable>[] include() default {};
    Class<? extends Throwable>[] exclude() default {};
    String label() default "";
    boolean stateful() default false;
    int maxAttempts() default 3;
    String maxAttemptsExpression() default "";
    Backoff backoff() default @Backoff;
    String exceptionExpression() default "";
    String[] listeners() default {};
}

說(shuō)明:

  •  value:拋出指定異常才會(huì)重試
  •  include:和value一樣,默認(rèn)為空,當(dāng)exclude也為空時(shí),默認(rèn)所有異常
  •  exclude:指定不處理的異常
  •  maxAttempts:最大重試次數(shù),默認(rèn)3次
  •  backoff:重試等待策略, 默認(rèn)使用@Backoff,@Backoff的value默認(rèn)為1000, 以毫秒為單位的延遲(默認(rèn) 1000)
  •  multiplier(指定延遲倍數(shù))默認(rèn)為0,表示固定暫停1秒后進(jìn)行重試,如果把multiplier設(shè)置為1.5,則第一次重試為2秒,第二次為3秒,第三次為4.5秒。

注解@Retryable切面類(lèi)

該注解主要的切面攔截器如下代碼,感興趣的小伙伴可以自行查看源碼,分析。

AnnotationAwareRetryOperationsInterceptor#invoke()

@Recover

Spring-Retry還提供了@Recover注解,用于@Retryable重試失敗后處理方法。如果不需要回調(diào)方法,可以直接不寫(xiě)回調(diào)方法,那么實(shí)現(xiàn)的效果是,重試次數(shù)完了后,如果還是沒(méi)成功沒(méi)符合業(yè)務(wù)判斷,就拋出異常。 可以看到傳參里面寫(xiě)的是Exception e,這個(gè)是作為回調(diào)的標(biāo)識(shí)(重試次數(shù)用完了,還是失敗,我們拋出這個(gè)Exception e通知觸發(fā)這個(gè)回調(diào)方法)。

注意事項(xiàng):

1、方法的返回值必須與@Retryable方法一致 

2、方法的第一個(gè)參數(shù),必須是Throwable類(lèi)型的,建議是與@Retryable配置的異常一致,其他的參數(shù),需要哪個(gè)參數(shù),寫(xiě)進(jìn)去就可以了(@Recover方法中有的) 

3、該回調(diào)方法與重試方法寫(xiě)在同一個(gè)實(shí)現(xiàn)類(lèi)里面 

4、由于是基于A(yíng)OP實(shí)現(xiàn),所以不支持類(lèi)里自調(diào)用方法 

5、如果重試失敗需要給@Recover注解的方法做后續(xù)處理,那這個(gè)重試的方法不能有返回值,只能是void 

6、方法內(nèi)不能使用try catch,只能往外拋異常 

7、@Recover注解來(lái)開(kāi)啟重試失敗后調(diào)用的方法(注意,需跟重處理方法在同一個(gè)類(lèi)中),此注解注釋的方法參數(shù)一定要是@Retryable拋出的異常。

該注解的代碼如下:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Import(RetryConfiguration.class)
@Documented
public @interface Recover {
}

注解@Recover切面類(lèi)

AnnotationAwareRetryOperationsInterceptor#getRecoverer()

寫(xiě)一個(gè)Demo 創(chuàng)建接口

首先我們創(chuàng)建一個(gè)接口。代碼如下:

public interface RetryService {
    /**
     * 重試方法
     * @param str
     * @return
     * @throws Exception
     */
    String retry(String str) throws Exception;
    /**
     * 回調(diào)方法
     * @param e
     * @param str
     * @return
     */
    String recover(Exception e,String str);
}

接口實(shí)現(xiàn)

上述接口的實(shí)現(xiàn)的代碼如下:

@Service
@Slf4j
public class RetryServiceImpl implements RetryService {
    /**
     * 重試方法
     * @param str
     * @return
     */
    @Override
    @Retryable(value = Exception.class,maxAttempts = 5,backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public String retry(String str) throws Exception {
        log.info("Service 請(qǐng)求入?yún)椋簕}",str);
        log.info("進(jìn)入測(cè)試方法,目前時(shí)間為:{}",new Date());
        if ("succ".equals(str)){
            return "succ";
        }else {
            throw new Exception("異常了!");
        }
    }
    /**
     * 重試次數(shù)完成后,回調(diào)的方法
     * @param e
     * @param str
     * @return
     */
    @Override
    @Recover
    public String recover(Exception e, String str) {
        log.info("異常出現(xiàn)后的回調(diào)操作,入?yún)椋簕},當(dāng)前時(shí)間為:{}", str,LocalDate.now());
        return null;
    }
}

測(cè)試

我們使用postman進(jìn)行測(cè)試

創(chuàng)建測(cè)試類(lèi)

我們創(chuàng)建一個(gè)控制器來(lái)測(cè)試功能。代碼如下:

@RestController
@Slf4j
public class RetryController {
    @Resource
    RetryService retryService;
    @GetMapping("/re")
    public String retry(@RequestParam("str") String str) throws Exception{
        log.info("Controller 請(qǐng)求入?yún)椋簕}",str);
        return retryService.retry(str);
    }
}

說(shuō)明:我們的入?yún)⑹且粋€(gè)字符串,若傳入的字符串非succ那么手動(dòng)拋出異常,我們觀(guān)察日志,看是否框架自動(dòng)發(fā)起了重試。

測(cè)試

我們啟動(dòng)Sping Boot項(xiàng)目,并且進(jìn)行測(cè)試,來(lái)看一下效果。

使用postman請(qǐng)求我們的login方法,我們觀(guān)察一下日志。請(qǐng)求地址localhost:8111/re,日志如下:

2023-07-17 21:05:19.488  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.controller.RetryController       : Controller 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:19.516  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:19.516  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 進(jìn)入測(cè)試方法,目前時(shí)間為:Mon Jul 17 21:05:19 CST 2023
2023-07-17 21:05:21.518  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:21.519  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 進(jìn)入測(cè)試方法,目前時(shí)間為:Mon Jul 17 21:05:21 CST 2023
2023-07-17 21:05:24.522  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:24.523  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 進(jìn)入測(cè)試方法,目前時(shí)間為:Mon Jul 17 21:05:24 CST 2023
2023-07-17 21:05:29.024  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:29.025  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 進(jìn)入測(cè)試方法,目前時(shí)間為:Mon Jul 17 21:05:29 CST 2023
2023-07-17 21:05:35.779  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請(qǐng)求入?yún)椋?11
2023-07-17 21:05:35.779  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 進(jìn)入測(cè)試方法,目前時(shí)間為:Mon Jul 17 21:05:35 CST 2023
2023-07-17 21:05:35.790  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : 異常出現(xiàn)后的回調(diào)操作,入?yún)椋?11,當(dāng)前時(shí)間為:2023-07-17

可以看到,出現(xiàn)異常后框架自動(dòng)發(fā)起了重試,在重試次數(shù)使用完成后,回調(diào)了異常處理的方法。

到此這篇關(guān)于Spring中的接口重試機(jī)制解析的文章就介紹到這了,更多相關(guān)Spring接口重試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 異常捕獲及處理案例詳解

    java 異常捕獲及處理案例詳解

    這篇文章主要介紹了java 異常捕獲及處理案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java通過(guò)MyBatis框架對(duì)MySQL數(shù)據(jù)進(jìn)行增刪查改的基本方法

    Java通過(guò)MyBatis框架對(duì)MySQL數(shù)據(jù)進(jìn)行增刪查改的基本方法

    MyBatis框架由Java的JDBC API進(jìn)一步封裝而來(lái),在操作數(shù)據(jù)庫(kù)方面效果拔群,接下來(lái)我們就一起來(lái)看看Java通過(guò)MyBatis框架對(duì)MySQL數(shù)據(jù)進(jìn)行增刪查改的基本方法:
    2016-06-06
  • java數(shù)據(jù)結(jié)構(gòu)-堆實(shí)現(xiàn)優(yōu)先隊(duì)列

    java數(shù)據(jù)結(jié)構(gòu)-堆實(shí)現(xiàn)優(yōu)先隊(duì)列

    通常都把隊(duì)列比喻成排隊(duì)買(mǎi)東西,大家都很守秩序,先排隊(duì)的人就先買(mǎi)東西。但是優(yōu)先隊(duì)列有所不同,它不遵循先進(jìn)先出的規(guī)則,而是根據(jù)隊(duì)列中元素的優(yōu)先權(quán),優(yōu)先權(quán)最大的先被取出,這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)-堆實(shí)現(xiàn)優(yōu)先隊(duì)列,感興趣的朋友一起看看吧
    2021-08-08
  • java Bean與json對(duì)象間的轉(zhuǎn)換實(shí)例講解

    java Bean與json對(duì)象間的轉(zhuǎn)換實(shí)例講解

    在本篇文章里小編給大家整理的是關(guān)于java Bean與json間的轉(zhuǎn)換的實(shí)例內(nèi)容,有需要的朋友們吧可以學(xué)習(xí)參考下。
    2020-01-01
  • 圖文并茂講解RocketMQ消息類(lèi)別

    圖文并茂講解RocketMQ消息類(lèi)別

    這篇文章主要介紹了圖文并茂講解RocketMQ消息類(lèi)別,RocketMQ對(duì)于消息提供了很多用法,包括:同步消息、異步消息、單向發(fā)送、順序消息、延時(shí)消息、批量消息、過(guò)濾消息、事務(wù)消息等
    2022-12-12
  • Mybatis Generator逆向工程的使用詳細(xì)教程

    Mybatis Generator逆向工程的使用詳細(xì)教程

    這篇文章主要介紹了Mybatis Generator逆向工程的使用詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • IDEA中make directory as的作用及說(shuō)明

    IDEA中make directory as的作用及說(shuō)明

    這篇文章主要介紹了IDEA中make directory as的作用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • Spring?Cloud?Gateway?服務(wù)網(wǎng)關(guān)的部署與使用詳細(xì)講解

    Spring?Cloud?Gateway?服務(wù)網(wǎng)關(guān)的部署與使用詳細(xì)講解

    這篇文章主要介紹了Spring?Cloud?Gateway?服務(wù)網(wǎng)關(guān)的部署與使用詳細(xì)介紹,本文給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Spring?createBeanInstance實(shí)例化Bean

    Spring?createBeanInstance實(shí)例化Bean

    這篇文章主要為大家介紹了Spring?createBeanInstance實(shí)例化Bean源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • JAVA抽象類(lèi)及接口使用方法解析

    JAVA抽象類(lèi)及接口使用方法解析

    這篇文章主要介紹了JAVA抽象類(lèi)及接口使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08

最新評(píng)論