Comet支持
Comet支持允许一个servlet异步处理IO,当数据在连接上可读的时候(而不是使用阻塞读)和往连接异步(最有可能的是来自一些其它原引发的事件)写回数据的时候接收事件。
CometEvent
实现了org.apache.catalina.CometProcessor接口的Sevlets有他们的事件激活方法而不是使用平常的服务方法,依照谁发生的事件。事件对象引发存取通常的request和respose对象,它可能使用平常的方式。重要的区别是这些对象在任何时候保持有效和全功能,在事件BEGIN开始到END或者ERROR事件结束。下面是这些事件类型:
◆ EventType.BEGIN: 在连接处理开始将被调用。它能被用来初始化任何在request和response对象中使用的相关字段。 在这个事件处理之后和结束处理开始或者错误事件之间,是可以使用response对象来在连接上进行异步写。注意,reponse对象和依靠的 OutputStream和Writer仍然不是同步的,因此当多个线程存取的时候,同步是强制的。在初始事件处理之后,request才会提交。
◆ EventType.READ: 这个指示输入数据可以用了,可以无阻塞的读了。可用的和InputStream或者Read的读方法可以用来决定是否有阻塞风险: servlet会读报告可用的数据,还进一步读取可用的数据。当遇到读错误的时候,servlet通过抛出异常来报告它。抛出异常会导致一个错误事件被激活,连接会被关闭。另外,可以捕捉异常,清理sevlet用到的数据结构,然后调用事件的close方法。尝试读取这个方法执行的request对象的数据是不允许的。
在一些平台上,例如Windows,一个客户端断开会有一个READ事件。从流读数据可能返回-1, IOException 或者 EOFException。确认你处理了所有这三种情况。如果你没有处理,Tomcat会立刻抛出你改捕捉事件,这个时候你会被通知错误。
◆ EventType.END:request 结束时调用。在开始方法中初始化的字段会被重置。在这个事件处理之后,request和response对象, 还有哪些依赖的对象,会被重新使用,用来处理其它的请求。 End在 数据可用和读文件结束的时候也会被调用。
◆ EventType.ERROR: 当容器在连接上遇到IO错误或者类似不可恢复的错误时,这个错误出现。在begin方法初始化的数据会被重置。这个事件处理之后,request和 response对象,还有一些依赖的对象,会被重新被其它请求使用。
这些事事件子类型,允许更详细的事件处理 (注意: 一些事件需要使用org.apache.catalina.valves.CometConnectionManagerValve 值):
◆ EventSubType.TIMEOUT: 连接超时 (ERROR子类型);注意这个错误类型不是致命的,连接不会被关闭除非servlet使用了事件的close方法.
◆ EventSubType.CLIENT_DISCONNECT: 客户端连接被关闭(ERROR子类型).事件的方法.
◆ EventSubType.IOEXCEPTION: 一个IO异常发生, 例如无效内容,一个无效的大块 (ERROR子类型).
◆ EventSubType.WEBAPP_RELOAD: web程序正在被重新加载T(END子类型).
◆ EventSubType.SESSION_END: sevlet结束会话 (END子类型).
就像上面描述的,典型的Comet请求生命周期将会包含一系列的事件:BEGIN -> READ -> READ -> READ -> ERROR/TIMEOUT. 在任何时候,servlet可以使用事件对象的close方法关闭请求的处理。
CometFilter
类似普通的过滤器,一个过滤器链会被激活当comet事件处理的时候。这些过滤器要应用CometFilter接口(他和平常的过滤器接口一样), 要被声明和影射在部署描述符中,和常规过滤器相同的方式。当处理一个事件的时候,过滤器链仅仅包括哪些匹配所使用影射规则的过滤器,也要实现 CometFiler接口.
例子代码
下面的伪代码servlet,实现了异步聊天功能,使用上面描述的API:
public class ChatServlet
extends HttpServlet implements CometProcessor {
protected ArrayList<HttpServletResponse> connections =
new ArrayList<HttpServletResponse>();
protected MessageSender messageSender = null;
public void init() throws ServletException {
messageSender = new MessageSender();
Thread messageSenderThread =
new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
messageSenderThread.setDaemon(true);
messageSenderThread.start();
}
public void destroy() {
connections.clear();
messageSender.stop();
messageSender = null;
}
/**
* Process the given Comet event.
*
* @param event The Comet event that will be processed
* @throws IOException
* @throws ServletException
*/
public void event(CometEvent event)
throws IOException, ServletException {
HttpServletRequest request = event.getHttpServletRequest();
HttpServletResponse response = event.getHttpServletResponse();
if (event.getEventType() == CometEvent.EventType.BEGIN) {
log("Begin for session: " + request.getSession(true).getId());
PrintWriter writer = response.getWriter();
writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
writer.println("<head><title>JSP Chat</title></head><body bgcolor=\"#FFFFFF\">");
writer.flush();
synchronized(connections) {
connections.add(response);
}
} else if (event.getEventType() == CometEvent.EventType.ERROR) {
log("Error for session: " + request.getSession(true).getId());
synchronized(connections) {
connections.remove(response);
}
event.close();
} else if (event.getEventType() == CometEvent.EventType.END) {
log("End for session: " + request.getSession(true).getId());
synchronized(connections) {
connections.remove(response);
}
PrintWriter writer = response.getWriter();
writer.println("</body></html>");
event.close();
} else if (event.getEventType() == CometEvent.EventType.READ) {
InputStream is = request.getInputStream();
byte[] buf = new byte[512];
do {
int n = is.read(buf); //can throw an IOException
if (n > 0) {
log("Read " + n + " bytes: " + new String(buf, 0, n)
+ " for session: " + request.getSession(true).getId());
} else if (n < 0) {
error(event, request, response);
return;
}
} while (is.available() > 0);
}
}
public class MessageSender implements Runnable {
protected boolean running = true;
protected ArrayList<String> messages = new ArrayList<String>();
public MessageSender() {
}
public void stop() {
running = false;
}
/**
* Add message for sending.
*/
public void send(String user, String message) {
synchronized (messages) {
messages.add("[" + user + "]: " + message);
messages.notify();
}
}
public void run() {
while (running) {
if (messages.size() == 0) {
try {
synchronized (messages) {
messages.wait();
}
} catch (InterruptedException e) {
// Ignore
}
}
synchronized (connections) {
String[] pendingMessages = null;
synchronized (messages) {
pendingMessages = messages.toArray(new String[0]);
messages.clear();
}
// Send any pending message on all the open connections
for (int i = 0; i < connections.size(); i++) {
try {
PrintWriter writer = connections.get(i).getWriter();
for (int j = 0; j < pendingMessages.length; j++) {
writer.println(pendingMessages[j] + "<br>");
}
writer.flush();
} catch (IOException e) {
log("IOExeption sending message", e);
}
}
}
}
}
}
}
Comet timeouts
如果你正在使用NIO连接器,你可以设置不同的延时为不同的comet连接。设置一个延时,像下面简单的设置一个属性就可以:
CometEvent event.... event.setTimeout(30*1000);
或者
event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));
这里设置延时30秒. 重要提示, 为了设置这个延时, 必须在BEGIN 事件之前设置, 默认值是soTimeout。 如果你正在使用APR连接器, 所有的Comet连接有相同的延时值,是soTimeout*50。
异步写
当 APR或者NIO启用的时候,Tomcat支持发送大的静态文件。这些写操作,系统负载一增加,就在更高效的方式上被异步执行。而不是使用阻塞模式发送大的response,写内容到一个静态文件时可以能的,写它用一个sendfile代码。一个缓存值可以用来缓存response数据到一个文件而不是内存。 Sendfile支持是可用的,如果request属性org.apache.tomcat.sendfile.support被设置成 Boolean.TRUE.
任何一个Servlet都可以指示Tomcat执行一个sendfile通过设置相应的response属性。当使用Sendfile的时候,最好确认request和response都没被包装,因为response主体将被connector随后发送,他不能被过滤。除了设置3个需要的response属性,servlet不发送任何response数据,但是它可以用来修改response头,例如设置 cookies。
◆ org.apache.tomcat.sendfile.filename: Canonical文件名, String类型
◆ org.apache.tomcat.sendfile.start: Start 偏移量,Long类型
◆ org.apache.tomcat.sendfile.start: End 偏移量,Long类型
分享到:
相关推荐
【标题】"comet4j+tomcat6+tomcat7并附完整版Demo" 提供的是一种在Java后端与前端之间实现长连接通信的解决方案,主要涉及到的技术包括Comet4j、Tomcat 6和Tomcat 7。Comet技术是用于实现实时Web应用的一种方法,它...
本文将深入探讨如何在Tomcat中开发一个Comet实例,这是一项用于实现服务器向客户端推送数据的技术,对于实时交互应用如聊天、股票更新或天气预报等场景非常关键。 Comet是一种持久连接技术,它打破了传统的HTTP请求...
标题中的"comet4j所需js与jar包(tomcat6与tomcat7)"表明,这个压缩包包含了Comet4J框架在Tomcat 6和Tomcat 7这两种版本的应用服务器上运行所需的JavaScript文件和Java类库。Tomcat是Apache软件基金会的一个开源...
前者基于 Servlet 2.5 的异步处理,后者是针对 Servlet 3.0 引入的,提供更简洁的推送接口。 3. **实现方法**: - **Blocking I/O**:Tomcat 使用的 `org.apache.catalina.connector.OutputBuffer` 类,当输出缓冲...
Tomcat7是Apache软件基金会的Apache Tomcat服务器的一个版本,它是一个开源的、实现了Java Servlet和JavaServer Pages(JSP)规范的应用服务器。Tomcat7因其轻量级、高效和易于管理的特性,在小型到中型企业级应用中...
总结来说,"test comet servlet"项目旨在探索和实现基于Java Servlet的Comet技术,通过异步通信提高Web应用的实时性能。项目中包含的"comet_test"文件可能涵盖了从服务器端代码到客户端交互的所有组件,以及必要的...
本示例介绍的是如何使用Comet4j这个第三方库来实现后台到前台的消息推送功能。Comet4j是一个专门用于JavaWeb应用的长连接通讯框架,它简化了基于Comet技术的实时通信实现。 首先,我们要理解Comet技术。Comet是一种...
配置Tomcat7以支持Comet技术,通常需要修改服务器的配置文件,如`server.xml`,设置`Connector`元素的`asyncTimeout`属性来支持长时间的HTTP连接,并开启异步处理。这允许服务器在处理完一个请求后不立即关闭连接,...
总之,Comet4j是一个强大的Web推送框架,通过结合Tomcat6或Tomcat7,可以轻松地实现服务器向客户端的实时数据推送,提升Web应用的用户体验。这个"comet4j.zip完整资源"包含了所有必要的组件,使得开发者能够快速地在...
在Connector标签中添加`asyncSupported="true"`属性,使Tomcat支持异步处理请求,这是实现长连接的基础。 接着,我们需要在项目中引入Comet4j库,并创建一个Comet服务端点。这个服务端点通常是一个Servlet,负责...
Spring整合DWR(Direct Web Remoting)和Comet技术,是一种高效的实现Web应用程序实时通信的解决方案,特别适用于创建如多人聊天室这样的实时交互应用。在这个项目中,Spring作为后端框架,负责业务逻辑处理和控制...
Tomcat通过使用AsyncContext和Servlet 3.0规范中的特性来实现Comet。Servlet 3.0引入了异步处理能力,允许Servlet在请求处理完成后继续运行,这样服务器可以在准备好数据后直接推送给客户端,而无需等待新的请求。...
6. **AsyncContext和 Comet技术**:Servlet 3.0引入了异步处理能力,通过`AsyncContext`可以在后台线程中执行长时间运行的任务,提高Web应用的响应性。Comet技术是一种长连接技术,通过保持客户端与服务器的连接来...
- Servlet 3.0及以上版本引入了AsyncContext,允许开发者创建异步Servlet,从而支持Comet技术。 - 使用Jetty或Tomcat等服务器的特定扩展,它们提供了对Comet的原生支持。 - 利用WebSocket,这是一种HTML5引入的全...
1. **Servlet容器**:Tomcat 7 支持Servlet 3.0规范,提供了诸如异步处理、过滤器链增强和注解支持等新特性。这使得开发者能够更方便地配置和管理Servlet。 2. **JSP支持**:它包含了对JSP 2.2的支持,提供了EL...
9. **Servlet API的高级特性**:如Asynchronous Servlet和 Comet技术,用于实现高效的异步通信和长轮询。 10. **JSP自定义标签**:深入介绍了如何创建和使用自定义标签库,以提高代码的可维护性和复用性。 11. **...
- Tomcat 7支持Java EE 6规范,引入了WebSocket和Comet支持。 - 版本7.0.79是7.x系列的一个安全更新版本,修复了一些已知的安全漏洞。 - 如果项目依赖Java EE 6特性且需要一定的安全性,7.0.79是较好的选择。 3....
在开发过程中,你可能需要结合使用多种技术,如使用 AJAX 实现客户端的异步请求,配合服务器端的 Comet 机制来达到实时推送的效果。同时,了解并优化服务器配置,如超时设置、连接池大小等,也是确保应用稳定性和...
14. **异步Servlet,Ajax,Comet**:讲解异步处理和长连接技术。 15. **Embedding Jetty**:如何将Jetty嵌入到应用程序中,实现轻量级部署。 16. **JEE服务器整合**:指导如何与Java EE服务器集成。 17. **开发...