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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

servlet异步请求

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 servlet异步请求 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、什么是servlet異步請求

Servlet 3.0 之前,一個普通 Servlet 的主要工作流程大致如下:

(1)、Servlet 接收到請求之后,可能需要對請求攜帶的數據進行一些預處理;

(2)、調用業務接口的某些方法,以完成業務處理;

(3)、根據處理的結果提交響應,Servlet 線程結束。

其中第二步處理業務邏輯時候很可以碰到比較耗時的任務,此時servlet主線程會阻塞等待完成業務處理,對于并發比較大的請求可能會產生性能瓶頸,則servlet3.0之后再此處做了調整,引入了異步的概念。

(1)、Servlet 接收到請求之后,可能需要對請求攜帶的數據進行一些預處理;

????(2)、調用業務接口的某些方法過程中request.startAsync()請求,獲取一個AsyncContext

????(3)、緊接著servlet線程退出(回收到線程池),但是響應response對象仍舊保持打開狀態,新增線程會使用AsyncContext處理并響應結果。

?????(4)、AsyncContext處理完成觸發某些監聽通知結果

2、Servlet異步請求示例

? ? ? ?2.1、示例準備

? ? ? ? ?本示例采用web.xml配置的形式,模擬場景為:筆者所在的it公司每周的工作內容,首先研發總監分配給產品、研發、測試相關的任務,布置完任務就出差(模擬請求響應),余下的各個小組進行自己任務操作(模擬的耗時操作),最終出周報完成任務(異步任務處理完成的通知)

? ?git地址:https://github.com/liushangzaibeijing/spsm.git? 分支:dev_async

? ? ? ?2.2、實現自定義的Servlet

/*** @ClassName AsyncServlet* @Desc 自定義異步Servlet處理器* @Author xieqx* @Date 2020/12/9 15:38**/ //通過注解的形式開始異步 @WebServlet(urlPatterns = "*.async",asyncSupported = true) public class AsyncServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//開啟異步支持//異步管理上下文resp.setCharacterEncoding("GBK");PrintWriter writer = resp.getWriter();writer.println("周工作任務布置開始");AsyncContext asyncContext = req.startAsync();asyncContext.start(new WeekTask(asyncContext));//添加監聽器 處理完成監聽asyncContext.addListener(new AsyncListener() {@Overridepublic void onComplete(AsyncEvent asyncEvent) throws IOException {System.out.println("工作在"+new Date()+"處理完成");}@Overridepublic void onTimeout(AsyncEvent asyncEvent) throws IOException {System.out.println("工作在"+new Date()+"處理超時");}@Overridepublic void onError(AsyncEvent asyncEvent) throws IOException {System.out.println("工作在"+new Date()+"處理出錯");}@Overridepublic void onStartAsync(AsyncEvent asyncEvent) throws IOException {System.out.println("工作在"+new Date()+"處理開始");}});writer.println("周工作任務布置完成");writer.flush();} }

? 開啟異步支持(默認異步支持不開啟)有兩種方式:

  • ? ?使用注解

  • web.xml配置

<servlet><servlet-name>asyncServlet</servlet-name><servlet-class>com.xiu.async.servlet.AsyncServlet</servlet-class><!-- 開啟servlet的異步請求操作 --><async-supported>true</async-supported></servlet><servlet-mapping><servlet-name>asyncServlet</servlet-name><url-pattern>*.async</url-pattern></servlet-mapping>

上述代碼中通過request.startAsync()啟動異步處理 返回一個異步上下文對象AsyncContext最終是使用該上下文對象來進行異步業務邏輯處理,其中有兩個核心方法?

asyncContext.start(new WeekTask(asyncContext)); 添加一個異步任務該任務是一個Runnable線程接口,這里就清晰了其實是servlet線程將處理任務交給另一個子線程,servlet直接返回從而達到提高系統吞吐量的作用。

對于異步請求可以我們需要獲取其中的結果,所有這里提供了監聽器模式添加事件監聽AsyncListener

onComplete 異步請求處理完成觸發 前提示需要調用?asyncContext.complete()方法(因為程序也不知道什么時候任務算是調用完畢了)
onTimeout 異步請求處理超時觸發,一般來說采用異步請求的任務都是比較耗時的任務,所以需要修改servlet默認的超時時間(修改的長一點)?
onError 異步處理錯誤的時候觸發
onStartAsync 異步處理開始的時候觸發即為request.startAsync(),因為添加監聽器在startAsync()方法后,所以第一個啟動是無法觸發該監聽的

這里異步處理只是簡單的打印了相關日志,不過真實的業務場景中可以寫復雜的業務處理邏輯。

3.3、異步任務

? ?這里提供相關的異步操作是實現runnable的線程實現類,同時這里提供了相關Job,PmJob(產品任務),RDJob(研發任務),TestJob(測試任務),每個任務模擬了10秒的耗時任務。

*** @ClassName WeekTask* @Desc 每周任務 * @Author xieqx* @Date 2020/12/10 9:36**/ public class WeekTask implements Runnable {private List<Job> jobs = null;private AsyncContext asyncContext = null;//這里初始化產品任務PmJob、研發任務RDJob 測試任務TestJobpublic WeekTask(AsyncContext asyncContext) {this.asyncContext = asyncContext;jobs = new ArrayList<>();PmJob pmJob = new PmJob();RDJob rdJob = new RDJob();TestJob testJob = new TestJob();jobs.add(pmJob);jobs.add(rdJob);jobs.add(testJob);}@Overridepublic void run() {for(Job job:jobs){job.execute();}System.out.println("周任務工作完成");//job執行完成后通知asyncContext.complete();} }

? PmJob

/*** @ClassName PmTask* @Desc 產品經理任務* @Author xieqx* @Date 2020/12/9 16:03**/ public class PmJob implements Job {@Overridepublic void execute() {System.out.println("產品經理開評審會議");try {Thread.sleep(10);System.out.println("模擬需求評審會議...");} catch (InterruptedException e) {e.printStackTrace();}} }

RDJob

/*** @ClassName PmTask* @Desc 研發任務* @Author xieqx* @Date 2020/12/9 16:03**/ public class RDJob implements Job {@Overridepublic void execute() {System.out.println("程序猿開始開發");try {Thread.sleep(10);System.out.println("程序猿哼哧哼哧干活中...");} catch (InterruptedException e) {e.printStackTrace();}} }

TestJob

/*** @ClassName TestJob* @Desc 測試任務* @Author xieqx* @Date 2020/12/9 16:03**/ public class TestJob implements Job {@Overridepublic void execute() {System.out.println("測試開始測試");try {Thread.sleep(10);System.out.println("測試用例測試...");} catch (InterruptedException e) {e.printStackTrace();}} }

3.4、測試場景

? ?請求立馬響應,但是異步任務在后面處理

??

總結

以上是生活随笔為你收集整理的servlet异步请求的全部內容,希望文章能夠幫你解決所遇到的問題。

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