servlet3.0 異步處理

 package com.yc.servlet;


import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;


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;


/**
 * 源辰信息
 * 異步訪問方式
 * 在Servlet3.0中,提供了AsyncContext,對異步執行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,
 * 用於啓動異步工作線程。而且AsynchContext還提供了Timeout等設置。
 * 你可以透過AsyncContext的getRequest() 、 getResponse()方法取得Request、Response對象,
 * 此時對客戶端的響應將暫緩至調用AsyncContext的complete()方法或dispatch()爲止,前者表示迴應完成,後者表示將響應調派給指定的URL 。
 * 若要能調用ServletRequest的startAsync()使用AsyncContext,則此Servlet 必須能支援非同步處理,如果使用@WebServlet來標註,
 * 則可以設定其asyncSupported爲true 。
 * 注意:使用異步處理方式,web容器的請求處理線程釋放了,可以服務其他的請求處理。
 * 但是該Request的處理並沒有結束,在使用AsyncContext的complete或者dispatch完成後,這個request的處理才結束。
 * web.xml的配置
 * <servlet>   
 * <servlet-name>AsyncServlet</servlet-name>   
 * <servlet-class>com.yc.servlet.AsyncServlet</servlet-class>   
 * <async-supported>true</async-supported>   
 * </servlet>   
 * @author navy
 * 2017年4月28日
 */
@WebServlet(urlPatterns="/asyncServlet",asyncSupported=true)
public class AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;


public AsyncServlet() {
super();
}


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}


protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");


long startTime = System.currentTimeMillis();
System.out.println("當前線程名:"+ Thread.currentThread().getName() 
+ " 線程ID:" + Thread.currentThread().getId());


//獲取異步執行上下文對象
AsyncContext asyncCtx = request.startAsync();


//給異步執行上下文對象添加監聽事件
asyncCtx.addListener(new AppAsyncListener());
asyncCtx.setTimeout(2000000); //異步請求超市時間


//獲取請求線程池
ThreadPoolExecutor executor = (ThreadPoolExecutor) request.getServletContext().getAttribute("executor");
executor.execute(new AsyncRequestProcessor(asyncCtx, 10000)); //使用異步方式處理請求

//非線程池方式
//new Thread(new AsyncRequestProcessor(asyncCtx, 10000)).start();


long endTime = System.currentTimeMillis();
System.out.println("當前線程名:"+ Thread.currentThread().getName() 
+ " 線程ID:" + Thread.currentThread().getId()
+ " 程序運行時長 " + (endTime - startTime) + " 毫秒 ");
}
}


 package com.yc.servlet;


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;


/**
 * 源辰信息
 * 應用程序啓動時創建一個線程池,用來給servlet的異步請求提供線程
 * @author navy
 * 2017年4月28日
 */
@WebListener
public class ApplicationListener implements ServletContextListener {
/**
* corePoolSize: 線程池維護線程的最少數量
* maximumPoolSize:線程池維護線程的最大數量
* keepAliveTime: 線程池維護線程所允許的空閒時間
* unit: 線程池維護線程所允許的空閒時間的單位
* workQueue: 線程池所使用的緩衝隊列
* handler: 線程池對拒絕任務的處理策略
*/
    @Override
    public void contextInitialized(ServletContextEvent sce) {
    System.out.println("初始化線程池開始...");
        ThreadPoolExecutor executor = new ThreadPoolExecutor(50,100,50000L,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5000));
        sce.getServletContext().setAttribute("executor", executor);
        System.out.println("初始化線程池完畢...");
    }


    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) sce.getServletContext().getAttribute("executor");
        executor.shutdown();
    }
}


 package com.yc.servlet;


import java.io.IOException;
import java.io.PrintWriter;


import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;


/**
 * 源辰信息
 * 異步servlet處理長時間任務的線程
 * @author navy
 * 2017年4月28日
 */
public class AsyncRequestProcessor implements Runnable {
    private AsyncContext asyncContext;
    private int milliseconds;


    public AsyncRequestProcessor() {


    }


    public AsyncRequestProcessor(AsyncContext asyncContext, int milliseconds) {
        this.asyncContext = asyncContext;
        this.milliseconds = milliseconds;
    }


    @Override
    public void run() {
    ServletRequest request=asyncContext.getRequest(); //從異步請求上下文對象中獲取請求對象
    String uname=request.getParameter("uname"); //獲取請求中的參數
System.out.println(uname);
        System.out.println(" 異步請求方式 :"+ asyncContext.getRequest().isAsyncSupported());
        
        try {
Thread.sleep(milliseconds); //休眠10秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
        
        try {
            PrintWriter out = asyncContext.getResponse().getWriter();
    out.write("請求處理10秒後...");
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        asyncContext.complete(); //完成異步請求
        //asyncContext.dispatch(""); //完成異步請求,跳轉到另外一個頁面
    }
}


 package com.yc.servlet;


import java.io.IOException;
import java.io.PrintWriter;


import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;


/**
 * 源辰信息
 * 異步監聽器,監聽異步servlet的過程
 * @author navy
 * 2017年4月28日
 */
@WebListener
public class AppAsyncListener implements AsyncListener {
    @Override
    public void onComplete(AsyncEvent event) throws IOException {
        System.out.println("異步servlet處理完成...");
    }


    @Override
    public void onTimeout(AsyncEvent event) throws IOException {
        ServletResponse response = event.getAsyncContext().getResponse();
        PrintWriter out = response.getWriter();
        out.write("異步servlet處理超時...");
        out.flush();
        out.close();


    }


    @Override
    public void onError(AsyncEvent event) throws IOException {
        ServletResponse response = event.getAsyncContext().getResponse();
        PrintWriter out = response.getWriter();
        out.write("異步servlet處理出錯...");
        out.flush();
        out.close();
    }


    @Override
    public void onStartAsync(AsyncEvent event) throws IOException {
        System.out.println("異步servlet處理開始...");
    }
}


package com.yc.servlet;


import java.io.IOException;
import java.io.PrintWriter;


import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * 源辰信息
 * 同步訪問方式
 * @author navy
 * 2017年4月28日
 */
@WebServlet(urlPatterns="/syncServlet")
public class SyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;


public SyncServlet() {
super();
}


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}


protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");


//獲取當前系統時間
long startTime = System.currentTimeMillis();
System.out.println("當前線程名:"+ Thread.currentThread().getName() 
+ " 線程ID:" + Thread.currentThread().getId());


String uname=request.getParameter("uname");
System.out.println(uname);






try {
Thread.sleep(10000);//休眠10秒
} catch (InterruptedException e) {
e.printStackTrace();



PrintWriter out = response.getWriter();
long endTime = System.currentTimeMillis();
out.write("請求處理10秒後...");
System.out.println("當前線程名:"+ Thread.currentThread().getName() 
+ " 線程ID:" + Thread.currentThread().getId()
+ " 程序運行時長 " + (endTime - startTime) + " 毫秒 ");
out.flush();
out.close();
}


}




<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>servlet3.0</title>
</head>
<body>
<h1>同步請求</h1>
<form action="syncServlet" method="post">
<label>用戶名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
<h1>異步請求</h1>
<form action="asyncServlet" method="post">
<label>用戶名:</label><input type="text" name="uname" value="源辰"/>
<input type="submit" value="提交" />
</form>
</body>
</html>
發佈了70 篇原創文章 · 獲贊 78 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章