⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resin-comet.xtp

📁 RESIN 3.2 最新源码
💻 XTP
字号:
<document>  <header>    <product>resin</product>    <title>Comet/Server-Push Servlet</title>    <description><p>Resin's server-push (Comet) servlet API enables streaming communication suchas reverse AJAX dynamic updates for browser/JavaScript applications.  The APIencapsulates of the threading and communications issues between therequest threads and the rest of the application.</p></description>  </header>  <body><s1><p>Resin's server-push (Comet) API lets server application push new data tothe client as it becomes available.  Administration and monitoringapplications need to continually update the client when new informationbecomes available to the server.</p><figure src="cometcomm.png"/><p>The architecture in the picture uses two HTTP streams to the serverapplication, one for normal client-server requests, and a secondunidirectional stream to send updates from the server to the client.In this example, we're using a browser with JavaScript, but the samearchitecture applies to a more sophisticated Flash monitoringapplication sending Hessian packets to update the monitoring display.</p></s1><localtoc/><s1 title="Example Overview"><p>The example updates a comet.html page every two seconds with new data.In this case, just an updated counter.</p><p>The components of the Comet/AJAX application look like:</p><ul><li>Protocol: JavaScript function calls with a trivial argument.</li><li>Client:  <ul>  <li>View: HTML updated by JavaScript AJAX</li>  <li>Controller: call server with an &lt;iframe></li>  </ul></li><li>Server:  <ul>  <li>Service: TimerService manages the comet connections and wakes themwith new data.</li>  <li>Servlet: TestCometServlet generates &lt;script> protocol tags fromnew data from the TimerService on each <code>resume</code>.</li>  <li>State: CometState encapsulates both the item's state (the timer count),and the <a href="http://caucho.com/resin-javadoc/com/caucho/servlet/comet/CometController.html">CometController</a> needed to wake the servlet andpass updated data.</li>  </ul></li></ul></s1><s1 title="Streaming Protocol: &lt;script> tags"><p>The comet HTTP stream is a sequence of &lt;script> tagscontaining JavaScript commands to update the browser's display.Because the browser executes the script as part of itsprogressive rendering, the user will see the updates immediately withoutwaiting for the entire HTTP request to complete.</p><p>In our example, the packet is a JavaScript<code>comet_update(data)</code> call, which updates the text field withnew data.  Here's an example of the packet stream:</p><example title="Update JavaScript packets">&lt;script type="text/javascript">window.parent.comet_update(1);&lt;/script>&lt;!-- 2 second delay -->&lt;script type="text/javascript">window.parent.comet_update(2);&lt;/script>&lt;!-- 2 second delay -->&lt;script type="text/javascript">window.parent.comet_update(3);&lt;/script></example><p>More sophisticated comet applications will usea <a href="http://hessian.caucho.com/doc/metaprotocol-taxonomy.xtp#Dynamic-Typed%20Metaprotocols">dynamic-typed protocol</a> to update the client.Browser-based applications could use JSON to update the client andFlash-based applications might use Hessian.  In all cases, the protocolmust be kept simple and designed for the client's requirements.  Designseparate, simple protocols for Flash and JavaScript browsers, rather thantrying to create some complicated general protocol.</p></s1><s1 title="Browser Client"><p>The JavaScript command stream updates a parent HTML file which definesthe JavaScript commands and launches the Comet servlet request with an&lt;iframe> tag.  Our <code>comet_update</code> function finds theHTML tag with <code>id="content"</code> and updates its HTML contentwith the new data from the server.</p><example title="comet.html">&lt;html>&lt;body>Server Data:&lt;span id="content">server data will be shown here&lt;/span>&lt;script type="text/javascript">function comet_update(value) {  document.getElementById('content').innerHTML = value;};&lt;/script>&lt;iframe src="comet"        style="width:1px;height:1px;position:absolute;top:-1000px">&lt;/iframe>&lt;/body>&lt;/html></example></s1><s1 title="CometController"><p>The <a href="http://caucho.com/resin-javadoc/com/caucho/servlet/comet/CometController.html">CometController</a> is Resin's thread-safe encapsulationof control and communication from the application's service to theComet servlet.  Applications may safely pass the <code>CometController</code>to different threads, wake the servlet with <code>wake()</code>, and senddata with <code>setAttribute</code>.</p><p>In the example, the <code>TimerService</code> passes the updatedcount to the servlet by calling<code>setAttribute("caucho.count", count)</code>, and wakes the servletby calling <code>wake()</code>.  When the servlet resumes, it willretrieve the count using <code>request.getAttribute("caucho.count")</code>.Note, applications must only use the thread-safe<code>CometController</code> in other threads.  As with other servlets, the<code>ServletRequest</code>, <code>ServletResponse</code>, writers andoutput stream can only be used by the servlet thread itself, never byany other threads.</p><example title="com.caucho.servlet.comet.CometController">package com.caucho.servlet.comet;public interface CometController{  public void wake();  public Object getAttribute(String name);  public void setAttribute(String name, Object value);  public void removeAttribute(String name);  public void close();}</example></s1><s1 title="Comet Servlet"><p>The comet servlet has three major responsibilities:</p><ol><li>Process the initial request (<code>service</code>).</li><li>Register the <code>CometController</code> with the service (<code>service</code>).</li><li>Send streaming data as it becomes available (<code>resume</code>).</li></ol><p>Like other servlets, only the comet servletmay use the <code>ServletRequest</code>, <code>ServletResponse</code> or anyoutput writer or stream.  No other thread may use these servlet objects,and the application must never store these objects in fields or objectsaccessible by other threads.  Even in a comet servlet, the servlet objectsare not thread-safe.  Other services and threads must usethe <code>CometController</code> to communicate with the servlet.</p><p><b>Process the initial request:</b> our servlet just calls<code>setContentType("text/html")</code>, since it's a trivial example.A real application would do necessary database lookups and possiblysend more complicated data to the client.</p><p><b>Register the <code>CometController</code>:</b>our servlet registers the controller with the timer service by calling<code>addCometState</code>. In general, the application state object willcontain the <code>CometController</code> as part of the registrationprocess.</p><p><b>Send streaming data:</b>.  The <code>TimerService</code> will set newdata in the <code>"comet.count"</code> attribute and <code>wake()</code>the controller.  When the servlet executes the <code>resume()</code> method,it will retrieve the data, and send the next packet to the client.</p><example title="example/TestCometServlet.java">package example;import java.io.*;import javax.servlet.http.*;import javax.servlet.*;import com.caucho.servlet.comet.GenericCometServlet;import com.caucho.servlet.comet.CometController;public class TestComet extends GenericCometServlet {  @Override  public boolean service(ServletRequest request,                         ServletResponse response,                         CometController controller)    throws IOException, ServletException  {    HttpServletRequest req = (HttpServletRequest) request;    HttpServletResponse res = (HttpServletResponse) response;    res.setContentType("text/html");    TestState state = new TestState(controller);    _service.addCometState(state);    return true;  }    @Override  public boolean resume(ServletRequest request,                        ServletResponse response,                        CometController controller)    throws IOException, ServletException  {    HttpServletRequest req = (HttpServletRequest) request;    HttpServletResponse res = (HttpServletResponse) response;    PrintWriter out = res.getWriter();    String count = req.getAttribute("comet.count");    out.print("&lt;script type='text/javascript'>");    out.print("comet_update(" + count + ");");    out.print("&lt;/script>");    return true;  }}</example><p>The connection can close for a number of reasons.  Either the<code>service()</code> or <code>resume()</code> methods may return false,telling Resin to close the connection.  The service might call<code>CometController.close()</code> which will also close the connection.Finally, the client may close the connection itself.</p><p>The sequence of calls for the example looks like the following:</p><ol><li><code>servlet.service()</code> is called for the initial request</li><li><code>_service.addCometState()</code> registers with the <code>TimerService</code></li><li>after the <code>service()</code> completes, Resin suspends the servlet.</li><li>The <code>TimerService</code> detects an event, in this case the timer event.</li><li>The <code>TimerService</code> calls <code>controller.setAttribute()</code> to send new data.</li><li>The <code>TimerService</code> calls <code>controller.wake()</code> to wake the servlet.</li><li><code>servlet.resume()</code> processes the data and sends the next packet.</li><li>After the <code>resume()</code> completes, Resin suspends the servlet again and we repeat as after step #3.</li><li>After the 10th data, the <code>TimerService</code> calls <code>controller.close()</code>, closing the servlet connection.</li></ol><s2 title="Comet Servlet State Machine"><p>The sequence of comet servlet calls looks like the following statemachine.  After the initial request, the servlet spends most of itstime suspended, waiting for the <code>TimerService</code> to call<code>wake()</code>.</p><figure src="cometstate.png"/></s2></s1>  </body></document>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -