日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何异步的处理restful服务(基础)

發布時間:2024/9/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何异步的处理restful服务(基础) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如何異步的處理restful服務(基礎)

1、使用Runnable

2、使用DeferredResult

3、異步處理的一些配置

?

?

正常請求方式

package com.nxz.controller;import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.Callable;/*** 異步處理的controller*/ @RestController @Slf4j public class AsyncController {//標準的同步處理邏輯@RequestMapping("/order")public String order() throws InterruptedException {log.info("主線城開始");Thread.sleep(1000);//具體的業務邏輯log.info("主線程返回");return "success";}}

?

1、通過callable異步方式

package com.nxz.controller;import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.Callable;/*** 異步處理的controller*/ @RestController @Slf4j public class AsyncController {//異步處理方式@RequestMapping("/order1")public Callable<String> order1() throws InterruptedException {log.info("主線城開始");Callable<String> callable = new Callable<String>() {@Overridepublic String call() throws Exception {log.info("副線程線程開始 callable.call()");Thread.sleep(1000);//具體的業務邏輯log.info("副線程線程結束 callable.call()");return "success";}};log.info("主線程返回");return callable;}}

訪問order1后日志輸出:日志表明主線程返回就代表請求已經結束,但是具體的數據信息是在副線程結束時

才返回的(也就是在主線程結束后tomcat等中間件是可以接受其他http請求,增大了吞吐量)

2019-04-29 20:28:32.433 INFO 16788 --- [nio-8080-exec-4] com.nxz.controller.AsyncController : 主線城開始 2019-04-29 20:28:32.434 INFO 16788 --- [nio-8080-exec-4] com.nxz.controller.AsyncController : 主線程返回 2019-04-29 20:28:32.434 INFO 16788 --- [ MvcAsync2] com.nxz.controller.AsyncController : 副線程線程開始 callable.call() 2019-04-29 20:28:33.435 INFO 16788 --- [ MvcAsync2] com.nxz.controller.AsyncController : 副線程線程結束 callable.call()

瀏覽器顯示結果時間??

?

?

2、DeferredResult形式

runnable形式的缺點:副線程的發起必須是在主線程下,但是企業級開發時,是比較復雜的。

DeferredResult是在應用1接受http請求后,由線程1將請求放到消息隊列中,然后又另一臺服務器具體啟用副線程執行邏輯,處理完成之后由線程二監聽消息隊列,接受返回數據,返回給前端

controller:

@Autowiredprivate MockQueue mockQueue;@Autowiredprivate DeferredResultHolder deferredResultHolder;//在主線程中是看不到副線程的任何東西的@RequestMapping("/order2")public DeferredResult<String> order2() throws InterruptedException {log.info("主線程開始");String orderNum = RandomStringUtils.randomNumeric(8);//模擬訂單號mockQueue.setPlaceOrder(orderNum);//模擬消息隊列(將訂單號放到消息隊里中)DeferredResult<String> result = new DeferredResult<>();deferredResultHolder.getMap().put(orderNum, result);log.info("主線程結束");return result;}

模擬隊列:

package com.nxz.async;import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component;/*** 模擬隊列的對象*/@Getter @Component @Slf4j public class MockQueue {//代表接受的信息private String placeOrder;//代表返回的消息private String complateOrder;//set 方法模擬往消息隊列中放消息public void setPlaceOrder(String placeOrder) throws InterruptedException {new Thread(() -> {log.info("接到請求消息" + placeOrder);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.complateOrder = placeOrder;log.info("接到請求消息處理完成" + placeOrder);}).start();}public void setComplateOrder(String complateOrder) {this.complateOrder = complateOrder;} }

?

異步監聽處理結果:

package com.nxz.async;import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component;//監聽器 @Component @Slf4j public class QueueListener implements ApplicationListener<ContextRefreshedEvent> {@Autowiredprivate MockQueue mockQueue;@Autowiredprivate DeferredResultHolder deferredResultHolder;/*** ContextRefreshedEvent這個事件是spring初始化完畢的一個事件* 監聽這個事件就是為了 在系統啟動完畢后要做什么事** @param contextRefreshedEvent*/@Overridepublic void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {log.info("接受返回結果的listener");new Thread(() -> {//將以下while循環放到一個單開的thred線程 防止主線程死循環//監聽mockqueue中的complateOrderwhile (true) {if (StringUtils.isNotBlank(mockQueue.getComplateOrder())) {String orderNum = mockQueue.getComplateOrder();//返回訂單處理結果log.info("返回訂單處理結果" + orderNum);deferredResultHolder.getMap().get(orderNum).setResult("place order success");mockQueue.setComplateOrder(null);//表名任務已經處理完了} else {//complateorder中沒有值是睡眠100毫秒try {log.info("沒有任務休眠100毫秒");Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();} }

?

?發送一個請求后,日志輸出:

2019-04-29 21:27:18.959 INFO 7176 --- [nio-8080-exec-3] com.nxz.controller.AsyncController : 主線程開始 2019-04-29 21:27:18.960 INFO 7176 --- [nio-8080-exec-3] com.nxz.controller.AsyncController : 主線程結束 2019-04-29 21:27:18.960 INFO 7176 --- [ Thread-43] com.nxz.async.MockQueue : 接到請求消息76311604 2019-04-29 21:27:19.961 INFO 7176 --- [ Thread-43] com.nxz.async.MockQueue : 接到請求消息處理完成76311604 2019-04-29 21:27:21.242 INFO 7176 --- [ Thread-30] com.nxz.async.QueueListener : 返回訂單處理結果76311604

?

?

?

posted @ 2019-04-29 22:29 巡山小妖N 閱讀(...) 評論(...) 編輯 收藏

總結

以上是生活随笔為你收集整理的如何异步的处理restful服务(基础)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。