作者:戴玉佩
精誠資訊 恆逸教育訓練中心 資深講師
Servlet 3.0增加了一項重要新功能:非同步處理。能夠將前端網頁送來的AJAX請求已非同步處理的方式,間接的提高處理效能。這裡要看到的是如何能夠在Servlet中啟動非同步處理,並在非同步處理過程中提供非同步事件控管的聆聽器AsyncListener。
要產生這樣的處理必須先有一個會發出AJAX請求的網頁。這樣一來,負責處理這請求的Servlet才能啟動非同步處理。程式如下:
//省略這裡的程式
@WebServlet(urlPatterns={"/async.do"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("");
request.setCharacterEncoding("utf-8");
String name = request.getParameter("name");
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
out.println("1. isAsyncStarted:" + request.isAsyncStarted()+"<br/>");
out.flush();
Integer i = (Integer)request.getAttribute("i");
if(i==null) {i = 1;}
else {i++;}
request.setAttribute("i", i);
try{
final AsyncContext ac = request.startAsync(); //這即啟動後端的非同步處理
//這裡將加入事件聆聽器的程式,先省略…
//這裡將會產生一個非同步處理的分支並將處理轉交給index.jsp,
ac.dispatch("/index.jsp");
}catch(Exception ex){
System.out.println("無法進入Async\n"+ex);
}
System.out.println("test:"+name);
out.println("3. isAsyncStarted:" + request.isAsyncStarted() + "<br/>");
out.println(request.getDispatcherType() + ", " + name);
out.flush();
}
//省略這裡的程式
程式碼1 AsyncServlet.java
當程式中啟動了非同步處理後,你可能會想要用一個非同步事件聆聽器的實作類別,來負責監控各分支中的處理狀況。Servlet 3.0 API中的AsyncListener介面中規範了非同步處理過程的4個事件。若想在非同步處理中監控所發生的事件,就必須寫一個類別來實作這個介面。在完成實作類別後,還要用AsyncContext的addAsyncListener(AsyncListener async)方法,將此事件物件註冊給該AsyncContext。因此在DD檔中無須為此事件實作類別加上<listener>的宣告。
因為非同步機制整個是在原來處理過程中分支出一個新的執行緒來處理請求與回應,以便讓原來的執行緒得以去處理後續的程式,無須等候。但這樣也讓原來的程式無法得知非同步模式中的處理過程發生了甚麼。這時就可以透過這個聆聽器的實作類別來加上控管程式了。
//省略這裡的程式
@WebServlet(urlPatterns={"/async.do"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//省略這裡的程式
try{
final AsyncContext ac = request.startAsync();
ac.addListener(new AsyncListener(){//這裡以一個匿名類別實作了事件聆聽器
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("Async 完成");
}
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("Async 發生Timeout");
}
public void onError(AsyncEvent event) throws IOException {
System.out.println(event.getThrowable());
}
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("Async 啟動");
}
});
ac.dispatch("/index.jsp");
}catch(Exception ex){
System.out.println("無法進入Async\n"+ex);
}
//省略這裡的程式
}//省略這裡的程式
程式碼2 AsyncServlet.java
可在課程中了解更多的Servlet相關資訊…
相關學習資源︰ SL-314-EE6 Java EE6 Java Servlet程式的開發與JSP技術
OCPJWCD Java Web元件系統開發專家認證訓練課程(原SCWCD)