`

Web服务器推送技术介绍及Cometd使用例子

 
阅读更多

传统模式的 Web 系统以客户端发出请求、服务器端响应的方式工作。不能满足很多现实应用的需求,譬如:

监控系统:后台硬件温度、电压发生变化;
即时通信系统:其它用户登录、发送信息;
即时报价系统:后台数据库内容发生变化;
即时信息系统:微博、说说实时推送

    目前主流的是采取如下几种方式来实现以上需求:

    Ajax轮询:异步响应机制,即通过不间断的客户端 Ajax 请求,去发现服务端的变化。这种方式由于是客户端主动连接的,所以会有一定程度的延时,并且服务器的压力也不小。

    长轮询:原理是客户端发出一个http长连接请求,然后等待服务器的响应,服务器接到请求之后,并不立即发送出数据,而是hold住这个Connecton。这个处理是非阻塞的,所以服务器可以继续处理其他请求。在某个时刻,比如服务器有新数据了,服务器再主动把这个消息推送出去,即通过之前建立好的连接将数据推送给客户端。客户端收到返回。这个时候就可以处理数据,然后再次发起新的长连接。服务器压力一般,实时性很高。Servlet 3.0开始已经支持该技术。sina微博就是使用的原生Servlet 3实现的消息推送。

    套接字:可以利用 Flash 的 XMLSocket 类或者 Java 的 Applet 来建立 Socket 连接,实现全双工的服务器推送,然后通过 Flash 或者Applet 与 JavaScript 通信的接口来实现最终的数据推送。但是这种方式需要 Flash 或者 JVM 的支持,同样不太合适于终端用户。

    HTML5的WebSocket:这种方式其实与套接字一样,但是这里需要单独强调一下:它是不需要用户而外安装任何插件的。HTML5 提供了一个 WebSocket 的 JavaScript 接口,可以直接与服务端建立Socket 连接,实现全双工通信,这种方式的服务器推送就是完全意义上的服务器推送了,没有半点模拟的成分,只是现阶段支持 HTML5 的浏览器并不多,而且一般老版本的各种浏览器基本都不支持。不过 HTML5 是一套非常好的标准,在将来,当HTML5 流行起来以后将是我们实现服务器推送技术的不二选择。

    Ajax轮训压力大,套接字不适用,HTML5目前支持不大多,这样看来长轮询是我们的必然之选。 可是使用 servlet 3 实现自己要做的事很多。没有有什么可供选择的框架呢?当然是有了,如下:

 1、Cometd

http://cometd.org/

    基于Bayeux协议实现,支持长轮询、WebSocket等..

 2、Pushlet

http://www.pushlets.com/

    基于HTTP流的JSP/Semlet技术实现

 3、Atmosphere

http://atmosphere.java.net/

 4、DWR

http://directwebremoting.org/dwr/index.html

        据我的了解,使用最多的应该是 DWR 和 Cometd了,其中Cometd功能强大使用又简单。我参与的一个项目中使用Cometd 做前台地图上人员轨迹的实时推送,几百个人员的实时轨迹推送都是没问题的。用。Cometd前台有2个实现版本 Jquery 和 Dojo,也可以用JS但是会复杂点。(PS Cometd 官方文档相当使用,遇到问题就读一遍,肯定能找到你想要的。 http://docs.cometd.org/reference/)

  如果你安装Maven了,以下2个简单的命令就能让你体验一把推送效果

 1、mvn archetype:generate -DarchetypeCatalog=http://cometd.org (选择任意一个)
 2、进入刚才创建的项目目录
 3、mvn install jetty:run
 4、前台访问 http://localhost:8080/刚才创建的项目名

    下面下载包我在项目中使用的实例。实例下载,请猛击这里 传送门

        你可能想向前台传送的数据是一个类而不仅仅是字符串,那么你可以使用Jackson让cometd帮你做自动的转换,而你的Java代码中是直接向客户端输出对象。甚至是List都可以。你需要如下操作:1、向前端输出的对象必须实现 Serializable , Cloneable 和 JSON.Convertible 接口

import java.util.Date;
import java.util.Map;
import org.eclipse.jetty.util.ajax.JSON;
import org.eclipse.jetty.util.ajax.JSON.Output;
import com.yixun.util.TimeUtil;
public class Alarmrecord implements java.io.Serializable  , Cloneable, JSON.Convertible{
	// Fields
	private Long recordid;
	private Readerinfo readerinfo;
	private Cardinfo cardinfo;
	private Position position;
	private Alarminfo alarminfo;
	private String alarmdetail;
	private Date recordtime;
	private String alarmType;
	private String alarmState;
	/**
	 * @see org.eclipse.jetty.util.ajax.JSON$Convertible#fromJSON(java.util.Map)
	 * @author simon
	 * create on Apr 14, 2012  11:58:41 AM
	 */
	public void fromJSON(Map map) {
		this.recordid = (Long) map.get("recordid");
		this.readerinfo = (Readerinfo) map.get("readerinfo");
		this.cardinfo = (Cardinfo) map.get("cardinfo");
		this.position = (Position) map.get("position");
		this.alarminfo = (Alarminfo) map.get("alarminfo");
		this.alarmdetail = (String) map.get("alarmdetail");
		this.alarmType = (String) map.get("alarmType");
		this.alarmState = (String) map.get("alarmState");
		this.recordtime = (Date) map.get("recordtime");
	}

	/**
	 * @see org.eclipse.jetty.util.ajax.JSON$Convertible#toJSON(org.eclipse.jetty.util.ajax.JSON.Output)
	 * @author simon
	 * create on Apr 14, 2012  11:58:46 AM
	 */
	public void toJSON(Output out) {
		out.add("recordid", recordid);
		out.add("readerinfo", readerinfo);
		out.add("cardinfo", cardinfo);
		out.add("position", position);
		out.add("alarminfo", alarminfo);
		out.add("alarmdetail", alarmdetail);
		out.add("recordtime", TimeUtil.format(recordtime,"yyyy-MM-dd HH:mm:ss"));
		out.add("alarmType", alarmType);
		out.add("alarmState", alarmState);
	}
}



2、Web.xml 中,org.cometd.server.CometdServlet 下添加 使用Jetty json 的参数。如下图:

         <!-- 报警推送 -->
	<servlet>
		<servlet-name>cometd</servlet-name>
		<servlet-class>org.cometd.server.CometdServlet</servlet-class>
		<init-param>
			<!-- 使用jetty json 模块 -->
			<param-name>jsonContext</param-name>
			<param-value>
				org.cometd.server.JettyJSONContextServer
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>cometd</servlet-name>
		<url-pattern>/cometd/*</url-pattern>
	</servlet-mapping>

	<servlet>
		<servlet-name>initializer</servlet-name>
		<servlet-class>
			com.yixun.epolice.action.comet.BayeuxInitializer
		</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<filter>
		<filter-name>cross-origin</filter-name>
		<filter-class>
			org.eclipse.jetty.servlets.CrossOriginFilter
		</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>cross-origin</filter-name>
		<url-pattern>/cometd/*</url-pattern>
	</filter-mapping>
	<filter>
		<filter-name>continuation</filter-name>
		<filter-class>
			org.eclipse.jetty.continuation.ContinuationFilter
		</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>continuation</filter-name>
		<url-pattern>/cometd/*</url-pattern>
	</filter-mapping>



3、OK,这样你后台就可以直接这样写来向前台写数据了,cometd会帮你做对象到Json的转换。

public  void update(Object o) {
		// 对 "/alarm" 频道广播消息
		if( null!= getBayeux().getChannel("/alarm") && o instanceof Alarmrecord ){
				getBayeux().getChannel("/alarm").publish(getServerSession(), (Alarmrecord)o,null);
		}
	}



4、前台这样获取数据:

if (handshake.successful === true)
            {
                cometd.batch(function()
                {
                    cometd.subscribe('/alarm', function(message)
                    {
                    	//对接收到的消息进行显示处理
                    	var alarm = message.data;
						if(len<1){ //如果初始时表中没有行
							$("#tableClass tbody").append("<tr bgcolor='#FFFFFF'>" +
							 "<td align='center'> <input type='checkbox' value='"+alarm.recordid+"'name='selecteditems'/></td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarm.cardinfo.cardid+"</td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarm.alarminfo.information+"</td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarm.alarmdetail+"</td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarm.position.positionName+"</td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarm.recordtime+"</td>"+
	   						 "<td nowrap='nowrap' align='center'>"+alarmState+"</td><tr>");
						}
                   cometd.publish('/service/alarm', { });
                });
            }

5、另外有一点要说的是 如果你向前台写的对象 AlarmRecord中包含其他对象如Positon ,那么Position对象也要实现 Serializable , Cloneable 和 JSON.Convertible 接口

    再次强调,官方文档很全很有用。另如果还有什么问题可以在文章下留言,大家互相探讨,互相学习。

 

转自:http://blog.csdn.net/majian_1987/article/details/8489488

分享到:
评论

相关推荐

    mycometd_push_Cometd_消息推送_

    CometD是一个开源的、基于Bayeux协议的双向通信框架,它允许Web服务器向客户端实时推送数据,而无需客户端不断发起请求。这种技术在现代Web应用中非常常见,尤其适用于实时聊天、股票更新、在线游戏等场景。下面将...

    cometd实例demo

    CometD是一个基于Bayeux协议的开源JavaScript库,它实现了服务器推送技术,允许服务器主动向客户端发送数据,而不仅仅是响应客户端的请求。这个“cometd实例demo”提供了使用CometD的一个实际示例,可以帮助开发者...

    cometd-2.9.1-distribution.tar.gz_Cometd_微信推送 java_推送

    CometD是一个开源的、基于Bayeux协议的实时通信框架,主要应用于构建WebSocket和Ajax的长连接,实现服务器向客户端的实时数据推送。在Java领域,CometD被广泛用于构建类似QQ聊天和微信这样的实时通讯应用。下面将...

    pushlet服务器推送技术

    在IBM于2008年发布的技术报告中,详细介绍了服务器推送技术——即所谓的Pushlet。这项技术为Web应用程序的发展带来了革命性的变化,尤其是在异步通信方面。本文将根据报告内容深入探讨Pushlet的相关知识点,包括其...

    cometd-1.0.0rc0 源码

    通过研究这个源码包,开发者不仅可以了解CometD的基本架构,还可以深入理解服务器推送技术的工作原理,这对于开发实时Web应用程序或者构建高性能的互动应用是非常有价值的。同时,对Jetty服务器的熟悉也会增强,因为...

    源码部署javaTomcat-cometd:CometD项目,用于Web消息传递的可扩展Comet(服务器推送)实现

    的可扩展彗星(服务器推送)实现。 CometD 版本 7.0.x ⇒ Java 11 - Jetty 11.0.x - jakarta.servlet.* 6.0.x ⇒ Java 11 - 码头 10.0.x - javax.servlet.* 5.0.x ⇒ Java 8 - 码头 9.4.x - javax.servlet.* CometD...

    Jetty cometd(Continuation)学习笔记

    【Jetty彗星技术(Cometd)及Continuation机制详解】 Jetty是一个高效、轻量级的Java Servlet容器,不仅可作为HTTP服务器,还能作为HTTP客户端。它以其小巧、稳定和高性能的特点受到广泛赞誉,适合企业级应用的需求。...

    CometD2.x官方帮助手册

    CometD是一个开源的、基于Java的WebSocket和Bayeux协议的实时Web应用程序框架,它使得服务器能够与浏览器或其他客户端进行双向通信,实现高效的推送服务。这个“CometD2.x官方帮助手册”是该技术的离线版文档,包含...

    cometd 框架实现的几个小程序

    用户发送的消息可以通过CometD服务直接推送到其他在线用户,无需客户端不断地轮询服务器获取新消息。这大大提高了用户体验,降低了服务器负载。 2. **注册功能**:注册通常涉及用户身份验证和授权。在CometD中,...

    cometd-java-oort-3.0.0.zip

    在Java编程领域,CometD是一个基于Bayeux协议的开源库,它实现了服务器推送技术,允许服务器主动向客户端发送数据,而不是等待客户端发起请求。CometD 3.0.0版本是其一个重要里程碑,这个版本可能包含了性能优化、新...

    CometD 简介

    ### CometD 简介 #### 一、CometD 概述 CometD 是一个基于 Bayeux 协议实现...通过以上介绍可以看出,CometD 提供了一种高效且灵活的方式来实现客户端与服务器之间的实时通信,适用于需要低延迟消息推送的应用场景。

    cometd-2.9.0-distribution.tar.gz

    总之,CometD 2.9.0提供了一整套解决方案来实现高效的实时Web通信,它简化了服务器推送技术的使用,让开发者可以专注于业务逻辑,而无需深入底层通信协议的复杂性。对于需要实现实时交互功能的Web应用来说,这是一个...

    cometd-jquery的jar

    总结来说,"cometd-jquery"的压缩包提供了使用jQuery进行CometD实时通信的必要工具,结合服务器端的Java实现,可以帮助开发者轻松创建实时Web应用。这种技术在需要即时更新和交互的场景中非常有用,比如在线聊天、...

    cometd注解实现java端代码实例

    通过spring的自动注入的功能,把cometd的服务可以注入到web controller中,controller可以调用cometd的服务方法向客户端发送任何需要的信息。网上很多例子都是客户端通过cometd的channel向其他客户端发送信息。很少...

    一种基于Terracotta的透明分布式CometD引擎实现.pdf

    1. **CometD引擎**:CometD是一个基于Bayeux协议的开放源代码项目,用于构建实时Web应用,通过长连接和服务器推送技术实现低延迟的双向通信。 2. **事件驱动Web应用**:这类应用强调实时交互,通常需要服务器主动推...

    Cometd 开发指南

    Comet技术主要是为了解决HTTP协议的短连接问题,允许服务器主动向客户端发送数据,而不是传统Web应用中客户端需要主动请求数据的模式。CometD支持多种协议,如HTTP和WebSocket。 在CometD系统中,客户端和服务端...

    cometd-3.0.0.beta2-distribution.tar.gz

    它提供了服务器推送技术,使得服务器可以主动向客户端发送数据,而不仅仅是响应客户端的请求。CometD的核心理念是通过长连接来实现双向通信,极大地提高了Web应用的交互性和实时性。 在"cometd-3.0.0.beta2-...

    dojo数据推送库

    通过使用dojo的cometd模块,开发者可以轻松地集成长连接或轮询机制,实现服务器到客户端的数据推送。 1. **安装与配置**:在项目中引入cometd-2.8.0库,根据服务器环境配置连接URL,设置长连接或轮询模式。 2. **...

    cometd-5.0.x.zip

    CometD是一个开源的、基于WebSocket的实时通信框架,它实现了Bayeux协议,使得Web应用可以实现双向通信,即服务器可以主动向客户端推送数据,而不仅仅是响应客户端的请求。在"cometd-5.0.x.zip"这个压缩包中,包含了...

    jquery-Bayeux数据推送

    jQuery-Bayeux就是基于comet技术的一个实现,它通过Bayeux协议提供服务器到客户端的数据推送服务。本文将深入探讨jQuery-Bayeux的核心概念、工作原理以及如何在项目中应用。 Bayeux协议是CometD项目定义的一种JSON...

Global site tag (gtag.js) - Google Analytics