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

SpringBoot的DeferredResult案例:DeferredResult的超時(shí)處理方式

 更新時(shí)間:2021年01月20日 09:38:35   作者:lxhjh  
這篇文章主要介紹了SpringBoot的DeferredResult案例:DeferredResult的超時(shí)處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧

DeferredResult的超時(shí)處理,采用委托機(jī)制,也就是在實(shí)例DeferredResult時(shí)給予一個(gè)超時(shí)時(shí)長(zhǎng)(毫秒),同時(shí)在onTimeout中委托(傳入)一個(gè)新的處理線程(我們可以認(rèn)為是超時(shí)線程);當(dāng)超時(shí)時(shí)間到來,DeferredResult啟動(dòng)超時(shí)線程,超時(shí)線程處理業(yè)務(wù),封裝返回?cái)?shù)據(jù),給DeferredResult賦值(正確返回的或錯(cuò)誤返回的)。

這個(gè)實(shí)例可以對(duì)上一個(gè)實(shí)例的代碼稍作改動(dòng)即可。

一、增加超時(shí)處理任務(wù)TimeOutWork

package com.example; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.async.DeferredResult;
 
public class TimeOutWork implements Runnable{ 
 private final Logger logger = LoggerFactory.getLogger(this.getClass());
 private DeferredResult<ResponseMsg<String>> deferredResult;
 
 public TimeOutWork(DeferredResult<ResponseMsg<String>> deferredResult) {
 this.deferredResult = deferredResult;
 }
 
 @Override
 public void run() {
 logger.debug("我超時(shí)啦!");
 ResponseMsg<String> msg = new ResponseMsg<String>();
 msg.fail("我超時(shí)啦!");
 //deferredResult.setResult(msg);
 deferredResult.setErrorResult(msg);
 }
}

二、DeferredResult請(qǐng)求中注冊(cè)超時(shí)任務(wù)處理

修改第一個(gè)請(qǐng)求,修改了兩處,請(qǐng)自己比較

package com.example; 
import java.util.HashMap;
import java.util.Map; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
 
@RestController
@RequestMapping("/api")
public class DeferredRestController {
 
 private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
 private final Map<Integer, DeferredResult<ResponseMsg<String>>> responseBodyMap = new HashMap<Integer, DeferredResult<ResponseMsg<String>>>();
 private final Map<Integer, RequestMsg> requestBodyMap = new HashMap<Integer, RequestMsg>();
 
 /**
 * 第一個(gè)請(qǐng)求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request1")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request1(RequestMsg req) {
 logger.debug("request1:請(qǐng)求參數(shù){}", req.getParam());
 DeferredResult<ResponseMsg<String>> result =new DeferredResult<ResponseMsg<String>>(10000l);//10秒
 result.onTimeout(new TimeOutWork(result));//超時(shí)任務(wù)
 requestBodyMap.put(1, req);// 把請(qǐng)求放到第一個(gè)請(qǐng)求map中
 responseBodyMap.put(1, result);// 把請(qǐng)求響應(yīng)的DeferredResult實(shí)體放到第一個(gè)響應(yīng)map中
 return result;
 }
 
 /**
 * 第二個(gè)請(qǐng)求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request2")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request2(RequestMsg req) {
 logger.debug("request2:請(qǐng)求參數(shù){}", req.getParam());
 DeferredResult<ResponseMsg<String>> result = new DeferredResult<ResponseMsg<String>>();
 requestBodyMap.put(2, req);// 把請(qǐng)求放到第二個(gè)請(qǐng)求map中
 responseBodyMap.put(2, result);// 把請(qǐng)求響應(yīng)的DeferredResult實(shí)體放到第二個(gè)響應(yīng)map中
 return result;
 }
 
 /**
 * 第三個(gè)請(qǐng)求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request3")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request3(RequestMsg req) {
 logger.debug("request3:請(qǐng)求參數(shù){}", req.getParam());
 DeferredResult<ResponseMsg<String>> result = new DeferredResult<ResponseMsg<String>>();
 requestBodyMap.put(3, req);// 把請(qǐng)求放到第三個(gè)請(qǐng)求map中
 responseBodyMap.put(3, result);// 把請(qǐng)求響應(yīng)的DeferredResult實(shí)體放到第三個(gè)響應(yīng)map中
 return result;
 }
 
 /**
 * 控制第x個(gè)請(qǐng)求執(zhí)行返回操作,同時(shí)自己也返回同樣的值
 * 
 * @param x
 * @return
 */
 @RequestMapping(value = "/requestXReturn", method = RequestMethod.POST)
 @ResponseBody
 public ResponseMsg<String> request1Return(Integer x) {
 ResponseMsg<String> msg = new ResponseMsg<String>();
 logger.debug("requestXReturn--1:請(qǐng)求參數(shù){}", x);
 DeferredResult<ResponseMsg<String>> result = responseBodyMap.get(x);
 if (result == null) {
 msg.fail("錯(cuò)誤!請(qǐng)求已經(jīng)釋放");
 return msg;
 }
 String resultStr = "result" + x.toString() + ". Received:" + requestBodyMap.get(x).getParam();
 msg.success("成功", resultStr);
 result.setResult(msg);// 設(shè)置DeferredResult的結(jié)果值,設(shè)置之后,它對(duì)應(yīng)的請(qǐng)求進(jìn)行返回處理
 responseBodyMap.remove(x);// 返回map刪除
 logger.debug("requestXReturn--2:請(qǐng)求參數(shù){}", x);
 logger.debug("requestXReturn--3:返回參數(shù){}", msg);
 return msg;
 }
}

三、修改頁面index.html

<script th:src="@{jquery-1.12.4.min.js}" type="text/javascript"></script>
 <script th:inline="javascript">
 function button1RequestClick(){
 var param=$("#request1RequestId").val();
 $.ajax({
  type:'post',
 url:'/api/request1',
 dataType : 'json',
 data : {
 'param' : param
 },
 success : function(data) {
 console.log(data);
 if (data.status==0){
  $("#request1ResultId").val(data.data);
 } else {
  $("#request1ResultId").val(data.msg);
 }
 },
 error : function(data) {
 console.log("button1RequestClick---error");
 console.log(data);
 //alert("錯(cuò)誤消息:" + data);
 }
 });
 };

前后的代碼都省略了,其實(shí)僅僅修改了

if (data.status==0){
 $("#request1ResultId").val(data.data);
} else {
 $("#request1ResultId").val(data.msg);
}

四、小結(jié)

DeferredResult的超時(shí)處理比較簡(jiǎn)單,定義時(shí)長(zhǎng)及注冊(cè)一個(gè)處理Runnable實(shí)例即可。對(duì)于setResult、setErrorResult還需要繼續(xù)研究。

1、setResult

2、setErrorResult

3、isSetOrExpired

補(bǔ)充:解決了DeferredResult請(qǐng)求長(zhǎng)時(shí)間占用數(shù)據(jù)庫連接的問題

最近看了看開源項(xiàng)目appllo配置中心的源碼,發(fā)現(xiàn)一個(gè)很有意思的東東:

(1)原理:由于使用了DeferredResult,根據(jù)Spring DispatcherServlet的默認(rèn)邏輯,數(shù)據(jù)庫連接只有在異步請(qǐng)求真正返回給客戶端的時(shí)候才會(huì)釋放回連接池

(2)應(yīng)用場(chǎng)景:長(zhǎng)連接時(shí)間很長(zhǎng),對(duì)于大部分請(qǐng)求可能都要數(shù)小時(shí)以上才會(huì)返回。在這么長(zhǎng)的一段時(shí)間內(nèi)一直占用著數(shù)據(jù)庫連接是不合理的

長(zhǎng)連接場(chǎng)景解決:

@Component
public class EntityManagerUtil extends EntityManagerFactoryAccessor {
 private static final Logger logger = LoggerFactory.getLogger(EntityManagerUtil.class);
 /**
 * close the entity manager.
 * Use it with caution! This is only intended for use with async request, which 
 * Spring won't close the entity manager until the async request is finished.
 */
 public void closeEntityManager() {
 EntityManagerHolder emHolder = (EntityManagerHolder)
 TransactionSynchronizationManager.getResource(getEntityManagerFactory());
 if (emHolder == null) {
 return;
 }
 logger.debug("Closing JPA EntityManager in EntityManagerUtil");
 EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
 }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • 全面剖析java 數(shù)據(jù)類型與運(yùn)算符

    全面剖析java 數(shù)據(jù)類型與運(yùn)算符

    這篇文章主要介紹了Java基本數(shù)據(jù)類型和運(yùn)算符,結(jié)合實(shí)例形式詳細(xì)分析了java基本數(shù)據(jù)類型、數(shù)據(jù)類型轉(zhuǎn)換、算術(shù)運(yùn)算符、邏輯運(yùn)算符等相關(guān)原理與操作技巧,需要的朋友可以參考下
    2021-09-09
  • 在IntelliJ IDEA中創(chuàng)建和運(yùn)行java/scala/spark程序的方法

    在IntelliJ IDEA中創(chuàng)建和運(yùn)行java/scala/spark程序的方法

    這篇文章主要介紹了在IntelliJ IDEA中創(chuàng)建和運(yùn)行java/scala/spark程序的教程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 淺談將子類對(duì)象賦值給父類對(duì)象

    淺談將子類對(duì)象賦值給父類對(duì)象

    淺談將子類對(duì)象賦值給父類對(duì)象...
    2006-12-12
  • MyBatis 多個(gè)條件使用Map傳遞參數(shù)進(jìn)行批量刪除方式

    MyBatis 多個(gè)條件使用Map傳遞參數(shù)進(jìn)行批量刪除方式

    這篇文章主要介紹了MyBatis 多個(gè)條件使用Map傳遞參數(shù)進(jìn)行批量刪除方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java實(shí)現(xiàn)斗地主游戲

    java實(shí)現(xiàn)斗地主游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)斗地主游戲,洗牌、發(fā)牌、看牌,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • java + dom4j.jar提取xml文檔內(nèi)容

    java + dom4j.jar提取xml文檔內(nèi)容

    這篇文章主要為大家詳細(xì)介紹了java + dom4j.jar提取xml文檔內(nèi)容,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Springboot項(xiàng)目快速實(shí)現(xiàn)過濾器功能

    Springboot項(xiàng)目快速實(shí)現(xiàn)過濾器功能

    上篇文章已經(jīng)給大家介紹了Springboot項(xiàng)目如何快速實(shí)現(xiàn)Aop功能,這篇文章給大家介紹Springboot項(xiàng)目如何快速實(shí)現(xiàn)過濾器功能,感興趣的小伙伴可以參考閱讀
    2023-03-03
  • SpringBoot整合JWT實(shí)戰(zhàn)教程

    SpringBoot整合JWT實(shí)戰(zhàn)教程

    JWT(JSON?Web?Token)是一種用于身份驗(yàn)證和授權(quán)的開放標(biāo)準(zhǔn)(RFC?7519),它使用JSON格式傳輸信息,可以在不同系統(tǒng)之間安全地傳遞數(shù)據(jù),這篇文章主要介紹了SpringBoot整合JWT實(shí)戰(zhàn)教程,需要的朋友可以參考下
    2023-06-06
  • Spring MVC 處理一個(gè)請(qǐng)求的流程

    Spring MVC 處理一個(gè)請(qǐng)求的流程

    Spring MVC是Spring系列框架中使用頻率最高的部分。不管是Spring Boot還是傳統(tǒng)的Spring項(xiàng)目,只要是Web項(xiàng)目都會(huì)使用到Spring MVC部分。因此程序員一定要熟練掌握MVC部分。本篇博客簡(jiǎn)要分析Spring MVC處理一個(gè)請(qǐng)求的流程。
    2021-02-02
  • Spring Boot 中application.yml與bootstrap.yml的區(qū)別

    Spring Boot 中application.yml與bootstrap.yml的區(qū)別

    其實(shí)yml和properties文件是一樣的原理,且一個(gè)項(xiàng)目上要么yml或者properties,二選一的存在。這篇文章給大家介紹了Spring Boot 中application.yml與bootstrap.yml的區(qū)別,感興趣的朋友一起看看吧
    2018-04-04

最新評(píng)論

修武县| 原平市| 金乡县| 彭州市| 肥乡县| 樟树市| 福贡县| 张北县| 沁阳市| 泗水县| 肇东市| 甘孜| 余江县| 四会市| 西贡区| 镇雄县| 安顺市| 潜山县| 呼和浩特市| 柯坪县| 长沙县| 隆林| 阳山县| 曲周县| 通城县| 盱眙县| 昌黎县| 申扎县| 星座| 陈巴尔虎旗| 顺昌县| 鄱阳县| 洛浦县| 鄂伦春自治旗| 大庆市| 扎鲁特旗| 阳山县| 阳信县| 邢台县| 海兴县| 乌海市|