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

詳解Spring DeferredResult異步操作使用場景

 更新時間:2021年10月25日 10:03:37   作者:yangguoqi  
本文主要介紹了Spring DeferredResult異步操作使用場景,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

為什么使用DeferredResult?

API接口需要在指定時間內(nèi)將異步操作的結(jié)果同步返回給前端時;

Controller處理耗時任務(wù),并且需要耗時任務(wù)的返回結(jié)果時;

當一個請求到達API接口,如果該API接口的return返回值是DeferredResult,在沒有超時或者DeferredResult對象設(shè)置setResult時,接口不會返回,但是Servlet容器線程會結(jié)束,DeferredResult另起線程來進行結(jié)果處理(即這種操作提升了服務(wù)短時間的吞吐能力),并setResult,如此以來這個請求不會占用服務(wù)連接池太久,如果超時或設(shè)置setResult,接口會立即返回。

使用DeferredResult的流程:

  • 瀏覽器發(fā)起異步請求
  • 請求到達服務(wù)端被掛起
  • 向瀏覽器進行響應(yīng),分為兩種情況:
    • 調(diào)用DeferredResult.setResult(),請求被喚醒,返回結(jié)果
    • 超時,返回一個你設(shè)定的結(jié)果
  • 瀏覽得到響應(yīng),再次重復1,處理此次響應(yīng)結(jié)果

給人一種異步處理業(yè)務(wù),但是卻同步返回的感覺。

場景

瀏覽器向A系統(tǒng)發(fā)起請求,該請求需要等到B系統(tǒng)(如MQ)給A推送數(shù)據(jù)時,A才會立刻向瀏覽器返回數(shù)據(jù);

如果指定時間內(nèi)B未給A推送數(shù)據(jù),則返回超時。

Demo代碼

接口代碼:

/get是調(diào)用A系統(tǒng)的接口返回數(shù)據(jù);

/result模擬B系統(tǒng)向A推送數(shù)據(jù)進行setResult。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
 
 
@RestController
@RequestMapping(value = "/deferred-result")
public class DeferredResultController {
 
    @Autowired
    private DeferredResultService deferredResultService;
 
    /**
     * 為了方便測試,簡單模擬一個
     * 多個請求用同一個requestId會出問題
     */
    private final String requestId = "haha";
 
 
    @GetMapping(value = "/get")
    public DeferredResult<DeferredResultResponse> get(@RequestParam(value = "timeout", required = false, defaultValue = "10000") Long timeout) {
        DeferredResult<DeferredResultResponse> deferredResult = new DeferredResult<>(timeout);
 
        deferredResultService.process(requestId, deferredResult);
 
        return deferredResult;
    }
 
    /**
     * 設(shè)置DeferredResult對象的result屬性,模擬異步操作
     * @param desired
     * @return
     */
    @GetMapping(value = "/result")
    public String settingResult(@RequestParam(value = "desired", required = false, defaultValue = "成功") String desired) {
        DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
        if (DeferredResultResponse.Msg.SUCCESS.getDesc().equals(desired)){
            deferredResultResponse.setCode(HttpStatus.OK.value());
            deferredResultResponse.setMsg(desired);
        }else{
            deferredResultResponse.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
            deferredResultResponse.setMsg(DeferredResultResponse.Msg.FAILED.getDesc());
        }
        deferredResultService.settingResult(requestId, deferredResultResponse);
 
        return "Done";
    }
}
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
 
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
 
@Service
public class DeferredResultService {
 
    private Map<String, Consumer<DeferredResultResponse>> taskMap;
 
    public DeferredResultService() {
        taskMap = new ConcurrentHashMap<>();
    }
 
    /**
     * 將請求id與setResult映射
     *
     * @param requestId
     * @param deferredResult
     */
    public void process(String requestId, DeferredResult<DeferredResultResponse> deferredResult) {
        // 請求超時的回調(diào)函數(shù)
        deferredResult.onTimeout(() -> {
            taskMap.remove(requestId);
            DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
            deferredResultResponse.setCode(HttpStatus.REQUEST_TIMEOUT.value());
            deferredResultResponse.setMsg(DeferredResultResponse.Msg.TIMEOUT.getDesc());
            deferredResult.setResult(deferredResultResponse);
        });
 
        Optional.ofNullable(taskMap)
                .filter(t -> !t.containsKey(requestId))
                .orElseThrow(() -> new IllegalArgumentException(String.format("requestId=%s is existing", requestId)));
 
        // 這里的Consumer,就相當于是傳入的DeferredResult對象的地址
        // 所以下面settingResult方法中"taskMap.get(requestId)"就是Controller層創(chuàng)建的對象
        taskMap.putIfAbsent(requestId, deferredResult::setResult);
    }
 
    /**
     * 這里相當于異步的操作方法
     * 設(shè)置DeferredResult對象的setResult方法
     *
     * @param requestId
     * @param deferredResultResponse
     */
    public void settingResult(String requestId, DeferredResultResponse deferredResultResponse) {
        if (taskMap.containsKey(requestId)) {
            Consumer<DeferredResultResponse> deferredResultResponseConsumer = taskMap.get(requestId);
            // 這里相當于DeferredResult對象的setResult方法
            deferredResultResponseConsumer.accept(deferredResultResponse);
            taskMap.remove(requestId);
        }
    }
 
}
import lombok.Data;
import lombok.Getter;
 
@Data
public class DeferredResultResponse {
    private Integer code;
    private String msg;
 
    public enum Msg {
        TIMEOUT("超時"),
        FAILED("失敗"),
        SUCCESS("成功");
 
        @Getter
        private String desc;
 
        Msg(String desc) {
            this.desc = desc;
        }
    }
}

測試

1. 超時

設(shè)置超時時間為8s,會一直阻塞8s,如果超時,返回默認超時的結(jié)果

 8s過去,沒有setResult,返回超時

2. 進行setResult

在阻塞期間調(diào)用setResult,我這里模擬的是B系統(tǒng)推送數(shù)據(jù)給A時拋異常失敗的情況,會立刻得到返回結(jié)果

總結(jié):

當有前端需要一個耗時操作服務(wù)時,可以使用DeferredResult異步機制編寫代碼。如果不用此功能,要么自己實現(xiàn)類似的功能。要么是前端輪訓去拉處理的結(jié)果,開發(fā)量比較大。有了DeferredResult可以節(jié)省很多我們前后端的開發(fā)量。

到此這篇關(guān)于詳解Spring DeferredResult異步操作使用場景的文章就介紹到這了,更多相關(guān)Spring DeferredResult異步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中的三級緩存與循環(huán)依賴詳解

    Spring中的三級緩存與循環(huán)依賴詳解

    Spring三級緩存是Spring框架中用于解決循環(huán)依賴問題的一種機制,這篇文章主要介紹了Spring三級緩存與循環(huán)依賴的相關(guān)知識,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2024-05-05
  • Java的Hibernate框架中的組合映射學習教程

    Java的Hibernate框架中的組合映射學習教程

    組合映射即是指主對象和子對象關(guān)聯(lián)且擁有相同的生命周期的映射關(guān)系,這里我們將舉一些數(shù)據(jù)操作的實例,來講解Java的Hibernate框架中的組合映射學習教程
    2016-07-07
  • SpringBoot開發(fā)之整合Mybatis詳解

    SpringBoot開發(fā)之整合Mybatis詳解

    這篇文章主要介紹了SpringBoot開發(fā)之整合Mybatis詳解,MyBatis是一個半自動的ORM框架,它允許我們通過編寫SQL語句來操作數(shù)據(jù)庫,使用MyBatis,我們可以通過定義映射文件(XML文件)或使用注解的方式將Java對象與數(shù)據(jù)庫表進行映射,需要的朋友可以參考下
    2023-09-09
  • SpringBoot集成ShedLock實現(xiàn)分布式定時任務(wù)流程詳解

    SpringBoot集成ShedLock實現(xiàn)分布式定時任務(wù)流程詳解

    ShedLock是一個鎖,官方解釋是他永遠只是一個鎖,并非是一個分布式任務(wù)調(diào)度器。一般shedLock被使用的場景是,你有個任務(wù),你只希望他在單個節(jié)點執(zhí)行,而不希望他并行執(zhí)行,而且這個任務(wù)是支持重復執(zhí)行的
    2023-02-02
  • SpringMVC攔截器實現(xiàn)登錄認證

    SpringMVC攔截器實現(xiàn)登錄認證

    這篇文章主要介紹了SpringMVC攔截器實現(xiàn)登錄認證的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Java深入數(shù)據(jù)結(jié)構(gòu)理解掌握抽象類與接口

    Java深入數(shù)據(jù)結(jié)構(gòu)理解掌握抽象類與接口

    在類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類稱為抽象類,接口是Java中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java抽象類和接口,感興趣的朋友一起看看吧
    2022-05-05
  • Java實現(xiàn)藍橋杯G將軍的示例代碼

    Java實現(xiàn)藍橋杯G將軍的示例代碼

    這篇文章主要介紹了Java實現(xiàn)藍橋杯G將軍的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • SpringBoot入口類和@SpringBootApplication講解

    SpringBoot入口類和@SpringBootApplication講解

    這篇文章主要介紹了SpringBoot入口類和@SpringBootApplication講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法

    Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法

    本文主要介紹了Java使用JNDI連接數(shù)據(jù)庫的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • JavaEE開發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    JavaEE開發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    本文主要介紹了如何在Eclipse中創(chuàng)建的Maven Project,本文是JavaEE開發(fā)的開篇,也是基礎(chǔ)。下面內(nèi)容主要包括了JDK1.8的安裝、JavaEE版本的Eclipse的安裝、Maven的安裝、Tomcat 9.0的配置、Eclipse上的M2Eclipse插件以及STS插件的安裝。
    2017-03-03

最新評論

武清区| 岳阳市| 景洪市| 孟州市| 平阳县| 铜山县| 贞丰县| 遂昌县| 承德市| 尼玛县| 南澳县| 嵊泗县| 益阳市| 阜宁县| 双柏县| 云梦县| 大名县| 恩施市| 江华| 新沂市| 亚东县| 思茅市| 兰西县| 革吉县| 抚顺市| 辉南县| 威信县| 桃园市| 北宁市| 金坛市| 郓城县| 故城县| 陵水| 即墨市| 乃东县| 正定县| 博野县| 宝清县| 舟山市| 河西区| 垣曲县|