我是CometD的新手。我用java和简单的CometD客户端编写了一个基本的CometD服务器,我得到了邮递员对/meta/握手、/meta/connect、/meta/订阅通道的成功响应。但是,当我开始使用我的cometD java客户机(我从https://protect-us.mimecast.com/s/vLH6CNk58of1Ow1GsmVz4u?domain=github.com中重用了它)时,握手失败了。
失败{supportedConnectionTypes=长轮询,通道=/meta/握手,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");
}
}发布于 2019-01-05 18:26:36
CometD版本、Jetty版本和Spring版本有一个奇怪的组合。我建议您坚持在CometD POM中声明的默认版本控制,即CometD 4.0.2、Jetty9.4.14和SpringBoot2.0.6。
您提到的握手失败不是完整的,也不是失败的握手回复。这是因为握手回复有successful字段,您提到的{supportedConnectionTypes=[long-polling], channel=/meta/handshake, id=22, version=1.0}看起来像握手请求。因此,很难说出问题是什么,因为故障原因通常会在握手回复中报告。
如果您已经在CometD Servlet映射下动态注册了/notifications 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信道),上面的代码还将通过deliver()在/updates信道上向客户端发送另一条消息,因此客户端将在/updates通道上接收两条不同的消息。这也许是你想要的,但大多数情况下并非如此。请在广播频道与服务频道的区别上读一读。
使用握手失败的详细信息更新问题,并对CometD、Jetty和Spring使用一致的版本控制。
https://stackoverflow.com/questions/54053880
复制相似问题