中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot項目中DeferredResult出現超時如何處理

發布時間:2021-01-20 14:23:01 來源:億速云 閱讀:1415 作者:Leah 欄目:開發技術

SpringBoot項目中DeferredResult出現超時如何處理?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

DeferredResult的超時處理,采用委托機制,也就是在實例DeferredResult時給予一個超時時長(毫秒),同時在onTimeout中委托(傳入)一個新的處理線程(我們可以認為是超時線程);當超時時間到來,DeferredResult啟動超時線程,超時線程處理業務,封裝返回數據,給DeferredResult賦值(正確返回的或錯誤返回的)。

一、增加超時處理任務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("我超時啦!");
 ResponseMsg<String> msg = new ResponseMsg<String>();
 msg.fail("我超時啦!");
 //deferredResult.setResult(msg);
 deferredResult.setErrorResult(msg);
 }
}

二、DeferredResult請求中注冊超時任務處理

修改第一個請求,修改了兩處,請自己比較

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>();
 
 /**
 * 第一個請求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request1")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request1(RequestMsg req) {
 logger.debug("request1:請求參數{}", req.getParam());
 DeferredResult<ResponseMsg<String>> result =new DeferredResult<ResponseMsg<String>>(10000l);//10秒
 result.onTimeout(new TimeOutWork(result));//超時任務
 requestBodyMap.put(1, req);// 把請求放到第一個請求map中
 responseBodyMap.put(1, result);// 把請求響應的DeferredResult實體放到第一個響應map中
 return result;
 }
 
 /**
 * 第二個請求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request2")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request2(RequestMsg req) {
 logger.debug("request2:請求參數{}", req.getParam());
 DeferredResult<ResponseMsg<String>> result = new DeferredResult<ResponseMsg<String>>();
 requestBodyMap.put(2, req);// 把請求放到第二個請求map中
 responseBodyMap.put(2, result);// 把請求響應的DeferredResult實體放到第二個響應map中
 return result;
 }
 
 /**
 * 第三個請求
 * 
 * @param req
 * @return
 */
 @RequestMapping("/request3")
 @ResponseBody
 public DeferredResult<ResponseMsg<String>> request3(RequestMsg req) {
 logger.debug("request3:請求參數{}", req.getParam());
 DeferredResult<ResponseMsg<String>> result = new DeferredResult<ResponseMsg<String>>();
 requestBodyMap.put(3, req);// 把請求放到第三個請求map中
 responseBodyMap.put(3, result);// 把請求響應的DeferredResult實體放到第三個響應map中
 return result;
 }
 
 /**
 * 控制第x個請求執行返回操作,同時自己也返回同樣的值
 * 
 * @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:請求參數{}", x);
 DeferredResult<ResponseMsg<String>> result = responseBodyMap.get(x);
 if (result == null) {
 msg.fail("錯誤!請求已經釋放");
 return msg;
 }
 String resultStr = "result" + x.toString() + ". Received:" + requestBodyMap.get(x).getParam();
 msg.success("成功", resultStr);
 result.setResult(msg);// 設置DeferredResult的結果值,設置之后,它對應的請求進行返回處理
 responseBodyMap.remove(x);// 返回map刪除
 logger.debug("requestXReturn--2:請求參數{}", x);
 logger.debug("requestXReturn--3:返回參數{}", 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("錯誤消息:" + data);
 }
 });
 };

前后的代碼都省略了,其實僅僅修改了

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

四、小結

DeferredResult的超時處理比較簡單,定義時長及注冊一個處理Runnable實例即可。對于setResult、setErrorResult還需要繼續研究。

1、setResult

SpringBoot項目中DeferredResult出現超時如何處理

2、setErrorResult

SpringBoot項目中DeferredResult出現超時如何處理

3、isSetOrExpired

SpringBoot項目中DeferredResult出現超時如何處理

補充:解決了DeferredResult請求長時間占用數據庫連接的問題

最近看了看開源項目appllo配置中心的源碼,發現一個很有意思的東東:

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

(2)應用場景:長連接時間很長,對于大部分請求可能都要數小時以上才會返回。在這么長的一段時間內一直占用著數據庫連接是不合理的

長連接場景解決:

@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());
 }
}

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

措美县| 拉孜县| 二连浩特市| 乌兰察布市| 江源县| 巫山县| 曲麻莱县| 多伦县| 屏南县| 通江县| 新闻| 家居| 蓝山县| 奉新县| 察隅县| 汨罗市| 临沧市| 额济纳旗| 资中县| 阿拉善左旗| 罗甸县| 凉城县| 方正县| 郴州市| 大渡口区| 迁安市| 呼伦贝尔市| 饶平县| 普安县| 昆明市| 元阳县| 九龙县| 思南县| 巨野县| 虞城县| 绥中县| 渭南市| 阳东县| 桐城市| 秦安县| 封丘县|