最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

背景

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

分析

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

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

實(shí)現(xiàn)

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

創(chuàng)建工程

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

<dependency>
   <groupId>org.springframework.retry</groupId>
   <artifactId>spring-retry</artifactId>
</dependency>
<!--AOP依賴-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

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

啟動(dòng)注解

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

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

說明:Spring重試機(jī)制主要是使用注解@Retryable來實(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 {};
}

說明:

  •  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切面類

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

AnnotationAwareRetryOperationsInterceptor#invoke()

@Recover

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

注意事項(xiàng):

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

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

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

4、由于是基于AOP實(shí)現(xiàn),所以不支持類里自調(diào)用方法 

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

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

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

該注解的代碼如下:

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

注解@Recover切面類

AnnotationAwareRetryOperationsInterceptor#getRecoverer()

寫一個(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 請求入?yún)椋簕}",str);
        log.info("進(jìn)入測試方法,目前時(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;
    }
}

測試

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

創(chuàng)建測試類

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

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

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

測試

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

使用postman請求我們的login方法,我們觀察一下日志。請求地址localhost:8111/re,日志如下:

2023-07-17 21:05:19.488  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.controller.RetryController       : Controller 請求入?yún)椋?11
2023-07-17 21:05:19.516  INFO 2007 --- [nio-8111-exec-2] o.t.s.l.service.impl.RetryServiceImpl    : Service 請求入?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)入測試方法,目前時(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 請求入?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)入測試方法,目前時(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 請求入?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)入測試方法,目前時(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 請求入?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)入測試方法,目前時(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 請求入?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)入測試方法,目前時(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在Java中使用OpenCV實(shí)踐

    在Java中使用OpenCV實(shí)踐

    用戶分享了在Java項(xiàng)目中集成OpenCV4.10.0的實(shí)踐經(jīng)驗(yàn),涵蓋庫簡介、Windows安裝、依賴配置及灰度圖測試,強(qiáng)調(diào)其在圖像處理領(lǐng)域的多功能性,并計(jì)劃后續(xù)探索AI結(jié)合應(yīng)用
    2025-07-07
  • 淺談JAVA在項(xiàng)目中如何自定義異常

    淺談JAVA在項(xiàng)目中如何自定義異常

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著JAVA在項(xiàng)目中如何自定義異常展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn)代碼

    基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn)代碼

    這篇文章主要介紹了基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn),從泛化調(diào)用實(shí)現(xiàn)的過程來看,我們可以對自己提供所有服務(wù)進(jìn)行測試,不需要引入調(diào)用的接口,減少代碼的侵入,需要的朋友可以參考下
    2022-04-04
  • Java實(shí)現(xiàn)讀取Excel數(shù)據(jù)并寫入到Word

    Java實(shí)現(xiàn)讀取Excel數(shù)據(jù)并寫入到Word

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)讀取Excel數(shù)據(jù)并寫入到Word功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-07-07
  • Spring中11個(gè)最常用的擴(kuò)展點(diǎn)總結(jié),你知道幾個(gè)

    Spring中11個(gè)最常用的擴(kuò)展點(diǎn)總結(jié),你知道幾個(gè)

    我們知道IOC(控制反轉(zhuǎn))和AOP(面向切面編程)是spring的基石,除此之外spring的擴(kuò)展能力非常強(qiáng),下面這篇文章主要給大家介紹了關(guān)于Spring中11個(gè)最常用的擴(kuò)展點(diǎn)的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • 一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    Docker可以讓開發(fā)者打包他們的應(yīng)用以及依賴包到一個(gè)輕量級、可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目打包成Docker鏡像的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Java實(shí)現(xiàn)跳躍表(skiplist)的簡單實(shí)例

    Java實(shí)現(xiàn)跳躍表(skiplist)的簡單實(shí)例

    這篇文章主要介紹了Java編程中跳躍表的概念和實(shí)現(xiàn)原理,并簡要敘述了它的結(jié)構(gòu),具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-09-09
  • Spring lazy-init 懶加載的原理小結(jié)

    Spring lazy-init 懶加載的原理小結(jié)

    lazy-init 是一個(gè)非常重要的屬性,可以優(yōu)化應(yīng)用的啟動(dòng)時(shí)間,尤其是在處理大量bean或者復(fù)雜依賴關(guān)系時(shí),可以顯著提高應(yīng)用的響應(yīng)速度,本文主要介紹了Spring lazy-init 懶加載的原理小結(jié),感興趣的可以了解一下
    2025-04-04
  • 深入解析Java中的JDBC事務(wù)

    深入解析Java中的JDBC事務(wù)

    這篇文章主要介紹了深入解析Java中的JDBC事務(wù),包含了Java多線程的事務(wù)并發(fā)等知識,需要的朋友可以參考下
    2015-08-08
  • SpringBoot請求參數(shù)傳遞與接收說明小結(jié)

    SpringBoot請求參數(shù)傳遞與接收說明小結(jié)

    這篇文章主要介紹了SpringBoot請求參數(shù)傳遞與接收,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12

最新評論

漾濞| 江门市| 江北区| 广宁县| 理塘县| 汉寿县| 镇平县| 连江县| 永城市| 安图县| 民和| 双城市| 永宁县| 柏乡县| 武清区| 哈密市| 潮州市| 嘉善县| 水富县| 曲松县| 安陆市| 灵丘县| 巴塘县| 调兵山市| 苗栗市| 皋兰县| 汝南县| 景宁| 达州市| 宁化县| 乃东县| 永清县| 扶沟县| 札达县| 邳州市| 兴业县| 和政县| 永修县| 新兴县| 金沙县| 化德县|