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

时间:2015-04-27 09:03:45

标签: java javascript spring cometd reverse-ajax

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

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

调试日志:

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通道上使用serverChannel.publish,那么在前端,没有文本附加到服务器。如果我使用remote.deliver而不是publish,则会附加正确的文本,但仅限于当前浏览器上的客户端,而不是其他浏览器中的其他客户端。如何使用serverChannel.publish将数据发送给所有订阅者,我的意思是正确的数据。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

请注意,由于您的JavaScript客户端(发件人)也订阅了频道/chat/1360,因此发件人在该频道上发布的任何邮件都将返回给发件人本身。这是CometD的default behaviour

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

您无需致电:

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

因为此时频道已经存在;你可以致电bayeux.getChannel(message.getChannel())

您正在做的是向服务器发送消息(messageA),然后您要处理服务器上的messageA字段并生成新的,已修改的消息({{1 }})广播给所有订阅者,包括原始发件人。

在这种情况下,您在service channel上发送messageB要好得多,因此不会向所有订阅者广播。 messageA不打算广播,它只是向服务器传达您想要做的事情的意思,并且服务频道正是为了这个目的而存在。

首先获取您的消息,您将看到所有其他消息都能正常运行。

您可以使用remote calls代替服务渠道,在您要对所发送邮件执行某些服务器端处理的特定情况下,它们更易于使用。

最后,使用监听器表示法查看channel parameters,而不是自己进行解析:

MessageA