java - Cometd 发布输入数据 Map 而不是等待服务器的输出

标签 java javascript spring cometd reverse-ajax

我正在开发一个 Spring-MVC 应用程序,它使用 Cometd 进行聊天。我面临的唯一问题是,当我从客户端发送消息时,客户端将该消息直接附加到服务器上,而不是等待我在后端调用发布机制,然后附加该内容。我在两台连接的不同计算机上尝试过,结果相同。因此,我无法访问我在后端设置的变量。

请让我知道我能做什么。非常感谢。

调试日志:

DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - <  {data={name=check123}, channel=/chat/1360}
wassup
DEBUG: org.cometd.server.BayeuxServerImpl.411c4c13 - Added channel /chat/1360
DEBUG: org.cometd.server.BayeuxServerImpl.411c4c13 - <  {data={accountid=1360, firstname=AKS, name=check123, channelname=/chat/1360, timestamp=2015-04-27 10:58:08.539}, channel=/chat/1360}
DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - << {channel=/chat/1360, id=10, successful=true}
DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - <  {channel=/chat/1360, id=10, successful=true}

在上面的调试日志中,第一行来自客户端,语句“wassup”打印在我的@Listener方法的开头。接下来,我添加一些数据并发布它,但我无法访问第三行提到的任何变量。任何想法。

这是 Java 代码:

@Named
@Singleton
@Service("chat")
public class ChatServiceImpl{

    @Inject
    private BayeuxServer bayeux;

    @Inject
    private PersonService personService;

    @Inject
    private ChatMessagesService chatService;

    @Inject
    private ConversationService conversationService;

    @Inject
    private RepliesService repliesService;

    @Session
    private ServerSession serverSession;

    @PostConstruct
    public void init(){
        System.out.println("Echo Service Initialized");
    }

    @PreDestroy
    public void cleanUp() throws Exception {
        System.out.println("Spring Container is destroyed");
    }


    @Listener(value = "/person/*")
    public void privateChat(ServerSession remote, ServerMessage.Mutable message){

        System.out.println("wassup");
        Person sender = this.personService.getCurrentlyAuthenticatedUser();
        String senderName = sender.getFirstName();

        Map<String,Object> input = message.getDataAsMap();
        String data = (String) input.get("name");
        String temp = message.getChannel();
        String temp1 = temp;
        temp = temp.replace("/person/","");
        final int conversationId = Integer.valueOf(temp);
        Map<String,Object> output = new HashMap<>();
        output.put("text",data);
        output.put("sender",senderName);
        output.put("channelname",temp);
        output.put("timestamp",new Timestamp(System.currentTimeMillis()));
        bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));
        ServerChannel serverChannel = bayeux.getChannel(message.getChannel());
        serverChannel.publish(remote,output);
        Thread thread = new Thread(() ->{
            Replies replies = new Replies();
            replies.setReplyingPersonName(senderName);
            replies.setReplyText(data);
            this.repliesService.addReply(replies,conversationId, sender);
        });
        thread.start();
    }


    @Listener("/chat/*")
    public void processChat(ServerSession remote, ServerMessage.Mutable message){
        System.out.println("wassup");
        String firstName = this.personService.returnLoggedInUsersName();
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());

        Map<String, Object> input = message.getDataAsMap();
        String data = (String)input.get("name");
        String temp = message.getChannel();
        String temp1 = temp;
        temp = temp.replace("/chat/","");
        final Long groupAccountIdentifier = Long.valueOf(temp);

        Map<String, Object> output = new HashMap<>();
        output.put("name",data);
        output.put("channelname",message.getChannel());
        output.put("firstname",firstName);
        output.put("timestamp",timestamp);
        output.put("accountid",groupAccountIdentifier);

        bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));
        ServerChannel serverChannel = bayeux.getChannel(message.getChannel());
        serverChannel.publish(serverSession,output);

        Thread thread = new Thread(() ->{
            ChatMessages chatMessages = new ChatMessages();
            chatMessages.setFirstName(firstName);
            chatMessages.setChatText(data);
            chatMessages.setChannelName(message.getChannel());
            chatMessages.setTimeStamp(new Timestamp((System.currentTimeMillis())));
            this.chatService.addChatMessage(chatMessages,groupAccountIdentifier);
        });
        thread.start();
    }
}

Javascript代码:

(function($)
{
    var cometd = $.cometd;

    $(document).ready(function()
    {
        function _connectionEstablished()
        {
            $('#body').append('<div>CometD Connection Established</div>');
        }

        function _connectionBroken()
        {
            $('#body').append('<div>CometD Connection Broken</div>');
        }

        function _connectionClosed()
        {
            $('#body').append('<div>CometD Connection Closed</div>');
        }

        // Function that manages the connection status with the Bayeux server
        var _connected = false;
        function _metaConnect(message)
        {
            if (cometd.isDisconnected())
            {
                _connected = false;
                _connectionClosed();
                return;
            }

            var wasConnected = _connected;
            _connected = message.successful === true;
            if (!wasConnected && _connected)
            {
                _connectionEstablished();
            }
            else if (wasConnected && !_connected)
            {
                _connectionBroken();
            }
        }

        // Function invoked when first contacting the server and
        // when the server has lost the state of this client
        function _metaHandshake(handshake)
        {
            if (handshake.successful === true)
            {
                cometd.batch(function()
                {
                    cometd.subscribe('/chat/1360', function(message)
                    {
                        $('#hello1').append('<div>Server Says: ' + message.data.name + ' ' + ' ' +message.data.firstname+'</div>');
                    });

                });
                cometd.publish('/chat/1360');
            }
        }

        // Disconnect when the page unloads
        $(window).unload(function()
        {
            cometd.disconnect(true);
        });

        var cometURL = location.protocol + "//" + location.host + config.contextPath + "/cometd";

        cometd.configure({
            url: cometURL,
            logLevel: 'debug'
        });

        cometd.addListener('/meta/handshake', _metaHandshake);
        cometd.addListener('/meta/connect', _metaConnect);
        cometd.handshake();
    });
})(jQuery);

如果有人有任何想法,请告诉我我能做什么。如果还有需要的信息,请随时询问。多谢。 :-)

更新

按照Sborder第二次的建议,我做了一些改变,但取得了部分成功。我还忘记添加我的index.jsp,它正在发送实际的文本消息。

首先,ChatServiceImpl:

     @Session
        private ServerSession serverSession;

  @Listener("/service/chat/{accountid}")
    public void processChat(ServerSession remote, ServerMessage.Mutable message,@Param("accountid")String accountid) {
        System.out.println("wassup and account id is "+accountid);
        String firstName = this.personService.returnLoggedInUsersName();
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());

        Map<String, Object> input = message.getDataAsMap();
        String text = (String) input.get("name");
        String temp = message.getChannel();
 Map<String, Object> data = new HashMap<String,Object>();
        data.put("name", text);
        data.put("channelname", message.getChannel());
        data.put("firstname", firstName);
        data.put("timestamp", timestamp);
     ServerChannel serverChannel = bayeux.createChannelIfAbsent("/chat/1306").getReference();
        serverChannel.setPersistent(true);
        System.out.println("Channel name is "+serverChannel.getChannelId());

       serverChannel.publish(remote, data);
    }

Application.js:

   function _metaHandshake(handshake)
    {
        if (handshake.successful === true)
        {
            cometd.batch(function()
            {
                cometd.subscribe('/chat/1306', function(message){
                    $('.hello1').append('<div>Server Says: ' +message.data.name + ' ' + ' ' +message.data.firstname+'</div>');

                });

            });

        }
    }

index.jsp:

 <div id="body">
    <input id="enterText" type="text" />Enter text
    <input id="sendMessage" type="button"/>
</div>

<div class="hello1">

</div>
<div class="hello123">

</div>

<script type="text/javascript">
    var config = {
        contextPath: '${pageContext.request.contextPath}'
    };
    var cometd = $.cometd;
    $(document).on("click", "#sendMessage", function(){
        var text = $("#enterText").val();
        cometd.publish('/service/chat/1306', { name: text});
    });

因此,如果我在/service channel 上使用 serverChannel.publish,那么在前端,不会将任何文本附加到服务器。如果我使用remote.deliver而不是发布,则会附加正确的文本,但仅附加到当前浏览器上的客户端,而不附加到其他浏览器中的其他客户端。如何使用 serverChannel.publish 将数据发送给所有订阅者,我的意思是正确的数据。

最佳答案

您的 JavaScript 客户端代码以错误的方式发布,只需调用:

cometd.publish('/chat/1360');

它缺少您要发送的数据,您至少应该使用一个空对象,如下所示:

cometd.publish('/chat/1360', {});

请注意,由于您的 JavaScript 客户端(发送者)也订阅了 channel /chat/1360 ,发送者在该 channel 上发布的任何消息都将返回给发送者本身。这是default behaviour cometd D。

最重要的是,在服务器端,您也可以通过ServerChannel.publish(...)在该 channel 上发布。 ,因此您要向该 channel 的订阅者发送另一条消息。

您无需调用:

bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));

因为此时 channel 已经存在;您可以调用bayeux.getChannel(message.getChannel()) .

您正在做的是将消息发送到服务器( messageA ),然后您要处理 messageA服务器上的字段并生成一条新的、修改后的消息 ( messageB ),以广播给所有订阅者,包括原始发送者。

在这种情况下,最好发送 messageAservice channel上因此它不会向所有订阅者广播。 MessageA并不是为了广播,它只是一种向服务器传达您想要执行的操作的方式,而服务 channel 正是为此目的而存在。

首先正确传达您的信息,然后您就会发现其余的一切都会顺利进行。

您可以使用remote calls在这种特殊情况下,当您想要对发送的消息执行一些服务器端处理时,它们比服务 channel 更容易使用。

最后,看看channel parameters ,而不是通过使用监听器符号自己进行解析:

@Listener("/chat/{accountId}")
public void processChat(ServerSession remote, ServerMessage.Mutable message, @Param("accountId") String account)
{
    ...
}

关于java - Cometd 发布输入数据 Map 而不是等待服务器的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29891370/

相关文章:

java - 使用简单的领域特定语言过滤集合

java - 获取 com.sun.xml.wss.XWSSecurityException 的 NoClassDefFoundError

java - 如何在 jquery ajax 成功方法中调用 spring Controller

java - 关于重复键更新 Java

java - 创建 zip 文件而不写入磁盘

java - JavaFX 应用程序中的通知

javascript - 轮播(图像 slider )与响应式菜单冲突

javascript - 无法使用其他值填充其他下拉菜单 - Javascript

javascript - facebook javascript sdk 使用 omniauth-facebook 获得额外权限

java - 如何在 Spring Boot 测试中连接到内存中的 HSQLDB 以进行查询