程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> 簡化Web應用開發 Servlet 3.0特性詳解(1)

簡化Web應用開發 Servlet 3.0特性詳解(1)

編輯:J2EE

Servlet 3.0作為Java EE6規范體系中一員,隨著Java EE6規范一起發布。之前51CTO也曾報導過《Java EE 6新特性之Servlet 3.0的異步處理》的相關內容,而本文將比較全面的、並結合代碼實例介紹Servlet 3.0的新特性。

關於Java EE 6平台的更多內容,51CTO推薦閱讀:Java EE 6平台指南

異步處理支持:有了該特性,Servlet線程不再需要一直阻塞,直到業務處理完畢才能再輸出響應,最後才結束該Servlet線程。在接收到請求之後,Servlet線程可以將耗時的操作委派給另一個線程來完成,自己在不生成響應的情況下返回至容器。針對業務處理較耗時的情況,這將大大減少服務器資源的占用,並且提高並發處理速度。

新增的注解支持:該版本新增了若干注解,用於簡化Servlet、過濾器(Filter)和監聽器(Listener)的聲明,這使得web.XML部署描述文件從該版本開始不再是必選的了。可插性支持:熟悉Struts2的開發者一定會對其通過插件的方式與包括Spring在內的各種常用框架的整合特性記憶猶新。

將相應的插件封裝成JAR包並放在類路徑下,Struts2運行時便能自動加載這些插件。現在Servlet 3.0提供了類似的特性,開發者可以通過插件的方式很方便的擴充已有Web應用的功能,而不需要修改原有的應用。下面我們將逐一講解這些新特性,通過下面的學習,讀者將能夠明晰了解Servlet 3.0的變化,並能夠順利使用它進行日常的開發工作。

異步處理支持

Servlet 3.0之前,一個普通Servlet的主要工作流程大致如下:首先,Servlet接收到請求之後,可能需要對請求攜帶的數據進行一些預處理;接著,調用業務接口的某些方法,以完成業務處理;最後,根據處理的結果提交響應,Servlet線程結束。

其中第二步的業務處理通常是最耗時的,這主要體現在數據庫操作,以及其它的跨網絡調用等,在此過程中,Servlet線程一直處於阻塞狀態,直到業務方法執行完畢。在處理業務的過程中,Servlet資源一直被占用而得不到釋放,對於並發較大的應用,這有可能造成性能的瓶頸。對此,在以前通常是采用私有解決方案來提前結束Servlet線程,並及時釋放資源。

Servlet 3.0針對這個問題做了開創性的工作,現在通過使用Servlet 3.0的異步處理支持,之前的Servlet處理流程可以調整為如下的過程:首先,Servlet接收到請求之後,可能首先需要對請求攜帶的數據進行一些預處理;接著,Servlet線程將請求轉交給一個異步線程來執行業務處理,線程本身返回至容器,此時Servlet還沒有生成響應數據,異步線程處理完業務以後,可以直接生成響應數據(異步線程擁有ServletRequest和ServletResponse對象的引用),或者將請求繼續轉發給其它Servlet。如此一來,Servlet線程不再是一直處於阻塞狀態以等待業務邏輯的處理,而是啟動異步線程之後可以立即返回。

異步處理特性可以應用於Servlet和過濾器兩種組件,由於異步處理的工作模式和普通工作模式在實現上有著本質的區別,因此默認情況下,Servlet和過濾器並沒有開啟異步處理特性,如果希望使用該特性,則必須按照如下的方式啟用:

對於使用傳統的部署描述文件(web.XML)配置Servlet和過濾器的情況,Servlet 3.0為<servlet>和<filter>標簽增加了<async-supported>子標簽,該標簽的默認取值為false,要啟用異步處理支持,則將其設為true即可。以Servlet為例,其配置方式如下所示:

  1. <servlet>
  2. <servlet-name>DemoServlet</servlet-name>
  3. <servlet-class>footmark.servlet.DemoServlet</servlet-class>
  4. <async-supported>true</async-supported>
  5. </servlet>

對於使用Servlet 3.0提供的@WebServlet和@WebFilter進行Servlet或過濾器配置的情況,這兩個注解都提供了asyncSupported屬性,默認該屬性的取值為false,要啟用異步處理支持,只需將該屬性設置為true即可。以@WebFilter為例,其配置方式如下所示:

  1. @WebFilter(urlPatterns="/demo",asyncSupported=true)
  2. publicclassDemoFilterimplementsFilter{...}

一個簡單的模擬異步處理的Servlet示例如下:

  1. @WebServlet(urlPatterns="/demo",asyncSupported=true)
  2. publicclassAsyncDemoServletextendsHttpServlet{
  3. @Override
  4. publicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)
  5. throwsIOException,ServletException{
  6. resp.setContentType("text/Html;charset=UTF-8");
  7. PrintWriterout=resp.getWriter();
  8. out.println("進入Servlet的時間:"+newDate()+".");
  9. out.flush();
  10. //在子線程中執行業務調用,並由其負責輸出響應,主線程退出
  11. AsyncContextctx=req.startAsync();
  12. newThread(newExecutor(ctx)).start();
  13. out.println("結束Servlet的時間:"+newDate()+".");
  14. out.flush();
  15. }
  16. }
  1. publicclassExecutorimplementsRunnable{
  2. privateAsyncContextctx=null;
  3. publicExecutor(AsyncContextctx){
  4. this.ctx=ctx;
  5. }
  6. publicvoidrun(){
  7. try{
  8. //等待十秒鐘,以模擬業務方法的執行
  9. Thread.sleep(10000);
  10. PrintWriterout=ctx.getResponse().getWriter();
  11. out.println("業務處理完畢的時間:"+newDate()+".");
  12. out.flush();
  13. ctx.complete();
  14. }catch(Exceptione){
  15. e.printStackTrace();
  16. }
  17. }
  18. }

除此之外,Servlet 3.0還為異步處理提供了一個監聽器,使用AsyncListener接口表示。它可以監控如下四種事件:

1.異步線程開始時,調用AsyncListener的onStartAsync(AsyncEventevent)方法;

2.異步線程出錯時,調用AsyncListener的onError(AsyncEventevent)方法;

3.異步線程執行超時,則調用AsyncListener的onTimeout(AsyncEventevent)方法;

4.異步執行完畢時,調用AsyncListener的onComplete(AsyncEventevent)方法;

要注冊一個AsyncListener,只需將准備好的AsyncListener對象傳遞給AsyncContext對象的addListener()方法即可,如下所示:

  1. AsyncContextctx=req.startAsync();
  2. ctx.addListener(newAsyncListener(){
  3. publicvoidonComplete(AsyncEventasyncEvent)throwsIOException{
  4. //做一些清理工作或者其他
  5. }
  6. ...
  7. });
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved