我是CometD的新手。我用Java和简单的CometD Client编写了一个基本的CometD Server。我从/ mana / handshake,/ meta / connect,/ meta / subscribe渠道获得邮递员的成功响应。但是,当我开始使用我的CometD Java客户端(从https://protect-us.mimecast.com/s/vLH6CNk58of1Ow1GsmVz4u?domain=github.com重用)时,握手失败,并显示以下消息。
失败{supportedConnectionTypes = [长轮询], channel = / meta / handshake,id = 22,version = 1.0}
我在我的代码中使用了CometdVersion-'4.0.0',jettyVersion-'9.4.0.v20161208',springbootVersion-'1.5.14.RELEASE'。
我已经向AnnotationCometDServlet完成了动态servlet注册,并添加了/ notifications作为映射。
我在bayeuxServer
配置类中创建了如下频道。
bayeuxServerImpl.createChannelIfAbsent("/updates",
(ServerChannel.Initializer) channel -> channel.addAuthorizer(GrantAuthorizer.GRANT_ALL));
在客户端代码中,我已将/ notifications用作默认网址,并将通道用作/ updates
@Service("cometListener")
@Slf4j
public class BayeuxListener implements BayeuxServer.SessionListener {
@Inject
private BayeuxServer bayeuxServer;
@Session
private ServerSession serverSession;
@Configure({"/updates**,/notifications**"})
protected void configureChannel(ConfigurableServerChannel channel) {
channel.addAuthorizer(GrantAuthorizer.GRANT_ALL);
channel.addAuthorizer(GrantAuthorizer.GRANT_PUBLISH);
channel.setPersistent(true);
}
@Listener("/meta/*")
public void monitorMeta(ServerSession session, ServerMessage message) {
log.info("monitoring meta"+message.toString()+"channel "+message.getChannel()+"session id "+session.getId());
}
@Listener("/meta/subscribe")
public void monitorSubscribe(ServerSession session, ServerMessage message) {
log.info("Monitored Subscribe from " + session + " for " + message.get(Message.SUBSCRIPTION_FIELD));
}
@Listener("/meta/unsubscribe")
public void monitorUnsubscribe(ServerSession session, ServerMessage message) {
log.info("Monitored Unsubscribe from " + session + " for " + message.get(Message.SUBSCRIPTION_FIELD));
}
@Listener("/updates")
public void handlesrgUpdates(ServerSession client, ServerMessage message) {
ServerSession cilentSession = bayeuxServer.getSession(client.getId());
client.deliver(cilentSession,"/updates", "Received message back from client");
}
}
答案 0 :(得分:0)
您有CometD版本,Jetty版本和Spring Boot版本的奇怪组合。我建议您坚持使用CometD POM中声明的默认版本,即CometD 4.0.2,Jetty 9.4.14和Spring Boot 2.0.6。
您提到的握手失败未完成或不是失败的握手回复。这是因为握手回复具有successful
字段,并且您提到的{supportedConnectionTypes=[long-polling], channel=/meta/handshake, id=22, version=1.0}
看起来像握手请求。因此,很难说出问题出在哪里,因为失败原因通常在握手回复中报告。
如果已在/notifications
Servlet映射下动态注册CometD Servlet,则客户端应具有以/notifications
结尾的URL。
请注意,Servlet映射/notifications
和CometD通道/notifications
是两个不同的东西,并不相关-它们恰好具有相同的名称。
您的代码大部分都可以,但是包含一些错误。
@Configure({"/updates**,/notifications**"})
protected void configureChannel(ConfigurableServerChannel channel) {
channel.addAuthorizer(GrantAuthorizer.GRANT_ALL);
channel.addAuthorizer(GrantAuthorizer.GRANT_PUBLISH);
channel.setPersistent(true);
}
上面的代码必须改为:
@Configure({"/updates/**,/notifications/**"})
protected void configureChannel(ConfigurableServerChannel channel) {
channel.addAuthorizer(GrantAuthorizer.GRANT_ALL);
channel.setPersistent(true);
}
请注意,频道切换必须在/
之后。
GRANT_PUBLISH
之后不需要GRANT_ALL
,其中包括GRANT_PUBLISH
。
配置方法应为public
,而不是protected
。
@Listener("/updates")
public void handlesrgUpdates(ServerSession client, ServerMessage message) {
ServerSession cilentSession = bayeuxServer.getSession(client.getId());
client.deliver(cilentSession,"/updates", "Received message back from client");
}
无需从clientSession
检索bayeuxServer
,因为它已作为参数client
传递给方法。
该方法可以更好地实现为:
@Listener("/updates")
public void handlesrgUpdates(ServerSession client, ServerMessage message) {
client.deliver(serverSession, "/updates", "Received message back from client");
}
请注意,消息的“发送者”是如何作为类的字段注入的serverSession
引用。
上面的代码仍然可能是错误的。
由于/updates
是广播频道,因此如果客户端订阅了/updates
频道,则当客户端将消息发布到/updates
频道时,它将从服务器接收回该消息(因为客户端订阅了/updates
通道),上面的代码还将通过/updates
在deliver()
通道上向客户端发送另一个消息,因此客户端将在/updates
频道上收到两条不同的消息。
这可能是您想要的,但大多数时候不是。
请阅读difference between broadcast channels and service channels。
使用握手失败的详细信息更新问题,并对CometD,Jetty和Spring Boot使用一致的版本。