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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持

發布時間:2023/12/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JAVA Web Servlet中的異步處理 (1) – Servlet3.0中的Async支持

每個請求來到Web容器,Web容器會為其分配一個線程來專門負責該請求,直到完成處理前,該執行線程都不會被釋放回容器。 執行線程會耗用系統資源,若有些請求需要長時間處理(例如長時間運算、等待某個資源),就會長時間占用執行線程。
若這類的請求很多,許多執行線程都被長時間占用,而在web容器內,可以使用的線程都是有限的,這對于系統就會是個負擔,甚至造成應用程式的性能瓶頸。

基本上一些需長時間處理的請求,通常客戶端也較不在乎請求后要有立即的回應。若可以,讓這類請求先釋放容器分配給該請求的執行線程,讓容器可以有機會將執行線程資源分配給其它的請求,可以減輕系統負擔。

釋放了容器所分配執行線程的請求,其回應將被延后,直到處理完成(例如長時間運算完成、所需資源已獲得)再行對客戶端的回應。

在Servlet 3.0中,提供了AsyncContext,對異步執行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,用于啟動異步工作線程。而且AsynchContext還提供了Timeout等設置。

你可以透過AsyncContext的getRequest() 、 getResponse()方法取得Request、Response對象,此次對客戶端的響應將暫緩至調用AsyncContext的complete()方法或dispatch()為止,前者表示回應完成,后者表示將響應調派給指定的URL 。

若要能調用ServletRequest的startAsync()使用AsyncContext,則此Servlet 必須能支援非同步處理,如果使用@WebServlet來標注,則可以設定其asyncSupported為true 。 例如:

@WebServlet(urlPatterns = "/some.do", asyncSupported = true ) public class AsyncServlet extends HttpServlet ...

如果使用web.xml設定Servlet,則可以設定標簽為true :

... <servlet> <servlet-name>AsyncServlet</servlet-name> <servlet-class>com.pkgname.AsyncServlet</servlet-class> <async-supported>true</async-supported> </servlet> ...

如果Servlet將會異步處理,若其前端有過濾器,則過濾器亦需標示其支援異步處理,如果使用@WebFilter ,同樣是可以設定其asyncSupported為true 。 例如:

@WebFilter(urlPatterns = "/some.do", asyncSupported = true ) public class AsyncFilter implements Filter{ ...

如果使用web.xml設定過濾器,則可以設定標簽為true :

... <filter> < filter -name>AsyncFilter</ filter -name> < filter -class>com.pkgname.AsyncFilter</ filter -class> <async-supported>true</async-supported> </ filter > ...

注意:
使用異步處理方式,web容器的請求處理線程釋放了,可以服務其他的請求處理。但是該Request的處理并沒有結束,在使用AsyncContext的complete或者dispatch完成后,這個request的處理才結束。

簡單的示例: package com.ss;import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date;import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;// import com.cndatacom.thread.BusinessHandleThread;/*** 異步處理Servlet* @author *//*** asyncSupported屬性默認是false,如果需要開啟支持異步處理功能,需要設置為true*/ @WebServlet(name = "AsyncServlet", urlPatterns = "/AsyncServlet2", asyncSupported = true) public class AsyncServlet2 extends HttpServlet {/*** */private static final long serialVersionUID = -2749650094193187229L;@Overrideprotected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();Date date = new Date(System.currentTimeMillis());SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");out.println("Servlet begin --" + sdf.format(date) + "<br>");// 響應輸出到客戶端// 進入異步模式,調用業務處理線程進行業務處理// Servlet不會被阻塞,而是直接往下執行// 業務處理完成后的回應由AsyncContext管理AsyncContext asyncContext = request.startAsync();BusinessWorkerThread businessHandleThread = new BusinessWorkerThread(asyncContext);Thread thread = new Thread(businessHandleThread);thread.start();//asyncContext.start(businessHandleThread);//也可以用這種方法啟動異步線程date = new Date(System.currentTimeMillis());out.println("Servlet end --" + sdf.format(date) + "<br>");out.flush();} } ------ package com.ss;import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date;import javax.servlet.AsyncContext; import javax.servlet.ServletResponse;/*** 業務處理線程* * @author */ public class BusinessWorkerThread implements Runnable {// 異步操作的上下文對象,通過構造方法傳進來private AsyncContext asyncContext;public BusinessWorkerThread(AsyncContext asyncContext) {this.asyncContext = asyncContext;}@Overridepublic void run() {try {// do some work...Thread.sleep(8000); // 和browser的timeout時間相關。如果browser上timeout是30s,則大于30時,網絡已經斷開。這是就會異常。ServletResponse response = asyncContext.getResponse();PrintWriter out = response.getWriter();Date date = new Date(System.currentTimeMillis());SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");out.println("business worker finished --"+ sdf.format(date));// 響應輸出到客戶端// 告訴啟動異步處理的Servlet異步處理已完成,Servlet就會提交請求響應asyncContext.complete();} catch (Exception e) {e.printStackTrace();}}} 輸出: 在瀏覽器中,輸出的內容按照后面的時間顯示在頁面上。 Servlet begin --22:33:57 +0800 Servlet end --22:33:57 +0800 business worker finished --22:34:05 +0800

注意: 使用瀏覽器訪問,因為各個瀏覽器的http請求超時設置不同,比如我的chrome是30秒。AsyncContext中對應的工作線程的持續時間需要小于瀏覽器的http超時時間。

AsyncListener

AsyncContext還可以設置一個Listener,對4個事件進行處理:

示例:

package com.ss;import java.io.IOException;import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** Servlet implementation class AsyncServletTest*/ @WebServlet(asyncSupported = true, urlPatterns = { "/AsyncTest" }) public class AsyncServletTest extends HttpServlet {String param = "";private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public AsyncServletTest() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse* response)*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 1 start asyncfinal AsyncContext ctx = req.startAsync();param = ctx.getRequest().getParameter("seq");System.out.println("getRequest request seq: " + param);// 2 set the timeoutctx.setTimeout(0);// 3 add listenerctx.addListener(new AsyncListener() {@Overridepublic void onTimeout(AsyncEvent arg0) throws IOException {System.out.println("onTimeout...");}@Overridepublic void onStartAsync(AsyncEvent arg0) throws IOException {System.out.println("onStartAsync...");}@Overridepublic void onError(AsyncEvent arg0) throws IOException {System.out.println("onError...");}@Overridepublic void onComplete(AsyncEvent arg0) throws IOException {System.out.println("onComplete...");}});// 4 run a threadctx.start(new Runnable() {@Overridepublic void run() {String seq = ctx.getRequest().getParameter("seq");System.out.println(">>>>>now respone: " + seq);int n = 0;try {// hold until receive exitwhile (!param.equals("exit")) {n++;if (n % 100000000 == 0) {System.out.println(seq + ": ..." + n); // }}ctx.getResponse().getWriter().write(seq+" -- "+n);} catch (IOException e) {e.printStackTrace();}ctx.complete();}});}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse* response)*/protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubSystem.out.println("doPost...");}} 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持的全部內容,希望文章能夠幫你解決所遇到的問題。

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