我想在我的项目中使用Comed,并在Tomcat7服务器上尝试了它的Jetty 8版本。它有效,但消息被发送了两次。
为了检查它是否与项目的其余部分有关,我只设置了一个具有此功能的独立项目,但我仍然收到两次消息。
我不知道为什么会这样。
项目中有5个文件:
- pom.xml
- web.xml
- index.html
- BayeuxInitializer.java
- FormDataService.java
以下是每个文件的代码:
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Sertal Vision</display-name> <servlet> <servlet-name>cometd</servlet-name> <servlet-class>org.cometd.server.CometdServlet</servlet-class> <init-param> <param-name>timeout</param-name> <param-value>60000</param-value> </init-param> <init-param> <param-name>logLevel</param-name> <param-value>3</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>bayeux-init</servlet-name> <servlet-class>ch.sertal.server.BayeuxInitializer</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cometd</servlet-name> <url-pattern>/cometd/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>bayeux-init</servlet-name> <url-pattern>/bayeux/servlet/*</url-pattern> </servlet-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> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
-
index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <script type="text/javascript" src="js/dojo/dojo/dojo.js"></script> <script type="text/javascript"> var subscription = undefined; dojo.addOnLoad( function () { dojo.require( "dojox.cometd" ); dojo.require("dojox.timing"); // Disconnect when the page unloads dojo.addOnUnload( function () { dojox.cometd.disconnect( true ); } ); var cometURL = "cometd"; dojox.cometd.init( cometURL ); var subscription = dojox.cometd.subscribe( "/sertal/formData", function ( message ) { dojo.create( "li", { innerHTML:message.data.count }, dojo.byId( "message-list" ) ); } ); i = 1; var t = new dojox.timing.Timer(); t.setInterval( 1000 ); t.onTick = function() { dojox.cometd.publish( '/sertal/formData', { count: i++ } ); }; t.start(); } ); </script> </head> <body> <div> <ul id="message-list"/> </div> </body> </html>
-
BayeuxInitializer.java
package ch.sertal.server; import org.cometd.bayeux.server.BayeuxServer; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; public class BayeuxInitializer extends GenericServlet { private static final long serialVersionUID = -9089442901563633963L; @Override public void init() throws ServletException { BayeuxServer bayeux = ( BayeuxServer ) getServletContext().getAttribute( BayeuxServer.ATTRIBUTE ); // new HelloService( bayeux ); new FormDataService( bayeux, getServletContext() ); } @Override public void service( ServletRequest servletRequest, ServletResponse servletResponse ) throws ServletException, IOException { throw new ServletException( "sorry :-)" ); } }
-
FormDataService.java
package ch.sertal.server; import org.cometd.bayeux.Message; import org.cometd.bayeux.server.BayeuxServer; import org.cometd.bayeux.server.ServerSession; import org.cometd.server.AbstractService; import javax.servlet.ServletContext; import java.util.Map; /** * Created by IntelliJ IDEA. * User: micha.roon * Date: 1/16/12 * Time: 12:25 PM * To change this template use File | Settings | File Templates. */ public class FormDataService extends AbstractService { private ServletContext context = null; public FormDataService( BayeuxServer bayeux, ServletContext context ) { super( bayeux, "hello" ); this.context = context; addService( "/sertal/formData", "processFormData" ); System.out.println( "New FormDataService" ); } public void processFormData( final ServerSession remote, Message message ) { Map<String, Object> input = message.getDataAsMap(); remote.deliver( getServerSession(), "/sertal/formData", input, null ); } }
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>BayeuxTest</groupId> <artifactId>BayeuxTest</artifactId> <version>1.0</version> <build> <plugins> <!--compiler plugin--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <version>1.1</version> <configuration> <username>${tomcat.username}</username> <password>${tomcat.password}</password> <url>${tomcat.manager}</url> <path>${tomcat.context}</path> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!--for cometd support--> <dependency> <groupId>org.cometd.java</groupId> <artifactId>bayeux-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>org.cometd.javascript</groupId> <artifactId>cometd-javascript-jquery</artifactId> <version>2.3.1</version> <type>war</type> </dependency> <dependency> <groupId>org.cometd.java</groupId> <artifactId>cometd-java-server</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlets</artifactId> <version>8.0.4.v20111024</version> <exclusions> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> </dependencies> </project>
当您使用普通频道(/sertal/formData)时,所有发布的帖子都将发送到所有订阅的客户端,在您的情况下,这是浏览器本身和Bayeux服务。因此,您将收到两个答案:一个是您发布的帖子,另一个是来自您的服务的回复。
解决方案:你不想publish
你的formData,你想要它deliver
ed:
...
t.onTick = function() {
dojox.cometd.deliver( '/sertal/formData', { count: i++ } );
};
...
还有其他解决方案,例如使用服务信道而不是正常信道。请参阅此CometD常见问题条目以获得进一步的解释。
更新:
我保留了在我的机器上实现这一点所必需的另一个更改:dojo.require
需要在addOnLoad
处理程序之外调用。
...
dojo.require("dojox.cometd");
dojo.require("dojox.timing");
dojo.addOnLoad(function () {
...
我一直在使用dojo v1.7.1。