聶永的博客

          記錄工作/學習的點點滴滴。

          Servlet 3.0筆記之異步請求相關方法和AsyncContext轉發等

          在ServletRequest中增加的有關異步相關方法分為:
          1. startAsync(servletRequest, servletResponse) 傳入指定的request和response對象,便于在AsyncContext中重復使用(這樣被Filter、Servlet包裝過的請求、相應對象才會在異步的環境下繼續生效)。
          2. startAsync() 若request或者response被包裝,將失去預期的效果。
          3. isAsyncSupported()isAsyncStarted()
            輔助性的方法,用于判斷當前請求是否支持異步或者異步已經開始。
          4. getAsyncContext()
            需要在異步啟動之后才能夠訪問,否則會報異常。
          在AsyncContext中分發的方法有三個,不太容易區分:
          1. AsyncContext.dispatch()
            若當前AsyncContext由ServletRequest.startAsync(ServletRequest, ServletResponse)方法啟動,返回的地址可以通過HttpServletRequest.getRequestURI()得到。
            否則,分發的地址則是當前URL request對象最后一次分發的地址。
            雖有些拗口,兩者分發的地址大部分情況下一致;但盡量使用帶有參數的異步上下文啟動器。
            如本例中請求/asyncDispatch2Async?disUrl=self,執行dispatch()方法之后,自身會再次分發到自身,包括傳遞的參數。
          2. AsyncContext.dispatch(String path)
            等同于ServletRequest.getRequestDispatcher(String)算是一個快捷方法。
            可以轉向一個同步或異步的servlet,或者JSP,或其它資源地址等。
          3. AsyncContext.dispatch(ServletContext context, String path)
            請求的地址將在給定的上下文里面(ServletContext),有有可能傳入的上下文與當前站帶你應用的上下文有所區別。
          展示一個較為有趣、但沒有多少實際意義的小示范:
          /**
          * 異步上下文的轉向分發
          *
          * @author yongboy
          * @date 2011-1-14
          * @version 1.0
          */
          @WebServlet(urlPatterns = { "/asyncDispatch2Async" }, asyncSupported = true)
          public class AsyncContextDispatch2AsyncServlet extends HttpServlet {
          private static final long serialVersionUID = 46172233331022236L;
          private static final Log log = LogFactory
          .getLog(AsyncContextDispatch2AsyncServlet.class);

          protected void doGet(HttpServletRequest request,
          HttpServletResponse response) throws ServletException, IOException {
          response.setHeader("Cache-Control", "private");
          response.setHeader("Pragma", "no-cache");
          response.setHeader("Connection", "Keep-Alive");
          response.setHeader("Proxy-Connection", "Keep-Alive");
          response.setContentType("text/html;charset=UTF-8");

          PrintWriter out = response.getWriter();
          out.println("

          Start ...

          ");
          out.flush();

          if (!request.isAsyncSupported()) {
          log.info("the servlet is not supported Async");
          return;
          }

          request.startAsync(request, response);

          if (request.isAsyncStarted()) {
          AsyncContext asyncContext = request.getAsyncContext();
          asyncContext.setTimeout(1L * 60L * 1000L);// 60sec

          new CounterThread(asyncContext).start();
          } else {
          log.error("the ruquest is not AsyncStarted !");
          }
          }

          private static class CounterThread extends Thread {
          private AsyncContext asyncContext;

          public CounterThread(AsyncContext asyncContext) {
          this.asyncContext = asyncContext;
          }

          @Override
          public void run() {
          int interval = 1000 * 20; // 20sec

          try {
          log.info("now sleep 20s, just as do some big task ...");
          Thread.sleep(interval);
          log.info("now dispatch to another Async Servlet");

          ServletRequest request = asyncContext.getRequest();

          String disUrl = request.getParameter("disUrl");

          if (StringUtils.isBlank(disUrl)) {
          disUrl = "/demoAsyncLink";
          }

          if (disUrl.endsWith(".jsp")) {
          request.setAttribute("dateStr", DateFormatUtils.format(
          System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
          }

          log.info("disUrl is : " + disUrl);

          // 將當前異步上下文所持有的request, response分發給Servlet容器
          if (StringUtils.equals("self", disUrl)) {
          // 將分發到自身,即當前異步請求地址
          asyncContext.dispatch();
          } else {
          // 將分發到指定的路徑
          asyncContext.dispatch(disUrl);
          }
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }
          }
          當前請求完成之后,將分發到下一個請求上面,若都是異步的Servlet,則很好的組成了異步Servlet請求鏈。
          有趣的地方在于,異步上下文環境可以分發到下一個異步或同步的servlet、jsp、html等資源。若訪問類似于如下地址,當前URL永遠不會斷開,又一個永動機,除非網絡鏈接出錯或者服務器關閉。
          http://localhost/servlet3/asyncDispatch2Async?disUrl=self
          一個視圖:
          image
          上面的異步Servlet總是在不斷的請求自我,成為了一個永動機;為disUrl傳入要轉發到的異步或同步的資源地址,組成一個鏈的模式,相當的簡單輕松。

          posted on 2011-01-17 21:07 nieyong 閱讀(12133) 評論(0)  編輯  收藏 所屬分類: Servlet3

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2011年1月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宣汉县| 兴义市| 芜湖市| 金秀| 大冶市| 新闻| 宜宾市| 武穴市| 富顺县| 大埔区| 南乐县| 贺州市| 河东区| 平陆县| 资溪县| 高安市| 浙江省| 莱西市| 宁化县| 滨州市| 武冈市| 福州市| 长垣县| 太仓市| 平顺县| 环江| 犍为县| 通化市| 河北省| 玛纳斯县| 区。| 阆中市| 新民市| 合水县| 兴国县| 云南省| 合作市| 彰化市| 阳春市| 镇安县| 洪洞县|