国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
comet之 Tomcat6 的servlet異步處理實現(xiàn)

comet之 Tomcat6 的servlet異步處理實現(xiàn)

文章分類:Java編程
Comet支持
  Comet支持允許一個servlet異步處理IO,當數(shù)據(jù)在連接上可讀的時候(而不是使用阻塞讀)和往連接異步(最有可能的是來自一些其它原引發(fā)的事件)寫回數(shù)據(jù)的時候接收事件。

CometEvent
  實現(xiàn)了org.apache.catalina.CometProcessor接口的Sevlets有他們的事件激活方法而不是使用平常的服務(wù)方法,依照誰發(fā)生的事件。事件對象引發(fā)存取通常的request和respose對象,它可能使用平常的方式。重要的區(qū)別是這些對象在任何時候保持有效和全功能,在事件BEGIN開始到END或者ERROR事件結(jié)束。下面是這些事件類型:

◆ EventType.BEGIN: 在連接處理開始將被調(diào)用。它能被用來初始化任何在request和response對象中使用的相關(guān)字段。 在這個事件處理之后和結(jié)束處理開始或者錯誤事件之間,是可以使用response對象來在連接上進行異步寫。注意,reponse對象和依靠的 OutputStream和Writer仍然不是同步的,因此當多個線程存取的時候,同步是強制的。在初始事件處理之后,request才會提交。
◆ EventType.READ: 這個指示輸入數(shù)據(jù)可以用了,可以無阻塞的讀了。可用的和InputStream或者Read的讀方法可以用來決定是否有阻塞風險: servlet會讀報告可用的數(shù)據(jù),還進一步讀取可用的數(shù)據(jù)。當遇到讀錯誤的時候,servlet通過拋出異常來報告它。拋出異常會導致一個錯誤事件被激活,連接會被關(guān)閉。另外,可以捕捉異常,清理sevlet用到的數(shù)據(jù)結(jié)構(gòu),然后調(diào)用事件的close方法。嘗試讀取這個方法執(zhí)行的request對象的數(shù)據(jù)是不允許的。
  在一些平臺上,例如Windows,一個客戶端斷開會有一個READ事件。從流讀數(shù)據(jù)可能返回-1, IOException 或者 EOFException。確認你處理了所有這三種情況。如果你沒有處理,Tomcat會立刻拋出你改捕捉事件,這個時候你會被通知錯誤。
◆ EventType.END:request 結(jié)束時調(diào)用。在開始方法中初始化的字段會被重置。在這個事件處理之后,request和response對象, 還有哪些依賴的對象,會被重新使用,用來處理其它的請求。 End在 數(shù)據(jù)可用和讀文件結(jié)束的時候也會被調(diào)用。
◆ EventType.ERROR: 當容器在連接上遇到IO錯誤或者類似不可恢復的錯誤時,這個錯誤出現(xiàn)。在begin方法初始化的數(shù)據(jù)會被重置。這個事件處理之后,request和 response對象,還有一些依賴的對象,會被重新被其它請求使用。

這些事事件子類型,允許更詳細的事件處理 (注意: 一些事件需要使用org.apache.catalina.valves.CometConnectionManagerValve 值):
◆ EventSubType.TIMEOUT: 連接超時 (ERROR子類型);注意這個錯誤類型不是致命的,連接不會被關(guān)閉除非servlet使用了事件的close方法.
◆ EventSubType.CLIENT_DISCONNECT: 客戶端連接被關(guān)閉(ERROR子類型).事件的方法.
◆ EventSubType.IOEXCEPTION: 一個IO異常發(fā)生, 例如無效內(nèi)容,一個無效的大塊 (ERROR子類型).
◆ EventSubType.WEBAPP_RELOAD: web程序正在被重新加載T(END子類型).
◆ EventSubType.SESSION_END: sevlet結(jié)束會話 (END子類型).
   就像上面描述的,典型的Comet請求生命周期將會包含一系列的事件:BEGIN -> READ -> READ -> READ -> ERROR/TIMEOUT. 在任何時候,servlet可以使用事件對象的close方法關(guān)閉請求的處理。

CometFilter

類似普通的過濾器,一個過濾器鏈會被激活當comet事件處理的時候。這些過濾器要應(yīng)用CometFilter接口(他和平常的過濾器接口一樣), 要被聲明和影射在部署描述符中,和常規(guī)過濾器相同的方式。當處理一個事件的時候,過濾器鏈僅僅包括哪些匹配所使用影射規(guī)則的過濾器,也要實現(xiàn) CometFiler接口.

例子代碼
  下面的偽代碼servlet,實現(xiàn)了異步聊天功能,使用上面描述的API:
Java代碼
  1. public class ChatServlet   
  2.        extends HttpServlet implements CometProcessor {   
  3.   
  4.        protected ArrayList<HttpServletResponse> connections =   
  5.            new ArrayList<HttpServletResponse>();   
  6.        protected MessageSender messageSender = null;   
  7.          
  8.        public void init() throws ServletException {   
  9.            messageSender = new MessageSender();   
  10.            Thread messageSenderThread =   
  11.                new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");   
  12.            messageSenderThread.setDaemon(true);   
  13.            messageSenderThread.start();   
  14.        }   
  15.   
  16.        public void destroy() {   
  17.            connections.clear();   
  18.            messageSender.stop();   
  19.            messageSender = null;   
  20.        }   
  21.   
  22.        /**  
  23.         * Process the given Comet event.  
  24.         *  
  25.         * @param event The Comet event that will be processed  
  26.         * @throws IOException  
  27.         * @throws ServletException  
  28.         */  
  29.        public void event(CometEvent event)   
  30.            throws IOException, ServletException {   
  31.            HttpServletRequest request = event.getHttpServletRequest();   
  32.            HttpServletResponse response = event.getHttpServletResponse();   
  33.            if (event.getEventType() == CometEvent.EventType.BEGIN) {   
  34.                log("Begin for session: " + request.getSession(true).getId());   
  35.                PrintWriter writer = response.getWriter();   
  36.                writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");   
  37.                writer.println("<head><title>JSP Chat</title></head><body bgcolor=\"#FFFFFF\">");   
  38.                writer.flush();   
  39.                synchronized(connections) {   
  40.                    connections.add(response);   
  41.                }   
  42.            } else if (event.getEventType() == CometEvent.EventType.ERROR) {   
  43.                log("Error for session: " + request.getSession(true).getId());   
  44.                synchronized(connections) {   
  45.                    connections.remove(response);   
  46.                }   
  47.                event.close();   
  48.            } else if (event.getEventType() == CometEvent.EventType.END) {   
  49.                log("End for session: " + request.getSession(true).getId());   
  50.                synchronized(connections) {   
  51.                    connections.remove(response);   
  52.                }   
  53.                PrintWriter writer = response.getWriter();   
  54.                writer.println("</body></html>");   
  55.                event.close();   
  56.            } else if (event.getEventType() == CometEvent.EventType.READ) {   
  57.                InputStream is = request.getInputStream();   
  58.                byte[] buf = new byte[512];   
  59.                do {   
  60.                    int n = is.read(buf); //can throw an IOException   
  61.                    if (n > 0) {   
  62.                        log("Read " + n + " bytes: " + new String(buf, 0, n)   
  63.                                + " for session: " + request.getSession(true).getId());   
  64.                    } else if (n < 0) {   
  65.                        error(event, request, response);   
  66.                        return;   
  67.                    }   
  68.                } while (is.available() > 0);   
  69.            }   
  70.        }   
  71.   
  72.        public class MessageSender implements Runnable {   
  73.   
  74.            protected boolean running = true;   
  75.            protected ArrayList<String> messages = new ArrayList<String>();   
  76.              
  77.            public MessageSender() {   
  78.            }   
  79.              
  80.            public void stop() {   
  81.                running = false;   
  82.            }   
  83.   
  84.            /**  
  85.             * Add message for sending.  
  86.             */  
  87.            public void send(String user, String message) {   
  88.                synchronized (messages) {   
  89.                    messages.add("[" + user + "]: " + message);   
  90.                    messages.notify();   
  91.                }   
  92.            }   
  93.   
  94.            public void run() {   
  95.   
  96.                while (running) {   
  97.   
  98.                    if (messages.size() == 0) {   
  99.                        try {   
  100.                            synchronized (messages) {   
  101.                                messages.wait();   
  102.                            }   
  103.                        } catch (InterruptedException e) {   
  104.                            // Ignore   
  105.                        }   
  106.                    }   
  107.   
  108.                    synchronized (connections) {   
  109.                        String[] pendingMessages = null;   
  110.                        synchronized (messages) {   
  111.                            pendingMessages = messages.toArray(new String[0]);   
  112.                            messages.clear();   
  113.                        }   
  114.                        // Send any pending message on all the open connections   
  115.                        for (int i = 0; i < connections.size(); i++) {   
  116.                            try {   
  117.                                PrintWriter writer = connections.get(i).getWriter();   
  118.                                for (int j = 0; j < pendingMessages.length; j++) {   
  119.                                    writer.println(pendingMessages[j] + "<br>");   
  120.                                }   
  121.                                writer.flush();   
  122.                            } catch (IOException e) {   
  123.                                log("IOExeption sending message", e);   
  124.                            }   
  125.                        }   
  126.                    }   
  127.   
  128.                }   
  129.   
  130.            }   
  131.   
  132.        }   
  133.   
  134.    }  


Comet timeouts
如果你正在使用NIO連接器,你可以設(shè)置不同的延時為不同的comet連接。設(shè)置一個延時,像下面簡單的設(shè)置一個屬性就可以:
CometEvent event.... event.setTimeout(30*1000);
或者
event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));

這里設(shè)置延時30秒. 重要提示, 為了設(shè)置這個延時, 必須在BEGIN 事件之前設(shè)置, 默認值是soTimeout。 如果你正在使用APR連接器, 所有的Comet連接有相同的延時值,是soTimeout*50。

異步寫

當 APR或者NIO啟用的時候,Tomcat支持發(fā)送大的靜態(tài)文件。這些寫操作,系統(tǒng)負載一增加,就在更高效的方式上被異步執(zhí)行。而不是使用阻塞模式發(fā)送大的response,寫內(nèi)容到一個靜態(tài)文件時可以能的,寫它用一個sendfile代碼。一個緩存值可以用來緩存response數(shù)據(jù)到一個文件而不是內(nèi)存。 Sendfile支持是可用的,如果request屬性org.apache.tomcat.sendfile.support被設(shè)置成 Boolean.TRUE.
  任何一個Servlet都可以指示Tomcat執(zhí)行一個sendfile通過設(shè)置相應(yīng)的response屬性。當使用Sendfile的時候,最好確認request和response都沒被包裝,因為response主體將被connector隨后發(fā)送,他不能被過濾。除了設(shè)置3個需要的response屬性,servlet不發(fā)送任何response數(shù)據(jù),但是它可以用來修改response頭,例如設(shè)置 cookies。

◆ org.apache.tomcat.sendfile.filename: Canonical文件名, String類型
◆ org.apache.tomcat.sendfile.start: Start 偏移量,Long類型
◆ org.apache.tomcat.sendfile.start: End 偏移量,Long類型
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Comet學習筆記(一)Tomcat與Comet - Shin - 博客園
web push
InfoQ: Web請求異步處理降低應(yīng)用依賴風險
Tomcat源碼分析
驚呆了!手寫4個mini版的tomcat!
Spring+JMS+ActiveMQ+Tomcat實現(xiàn)消息服務(wù)
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服