【问题标题】:Chat by JMS. How to link components ? (wicket, activemq, j2ee)通过 JMS 聊天。如何链接组件? (检票口,activemq,j2ee)
【发布时间】:2013-06-29 05:14:17
【问题描述】:

我有一些架构问题。我开发了一个在 glassfish appserver 上运行的 wicket web-app,有一些 ejb 模块等。要创建聊天面板,我想使用某种 JMS,例如 Apache ActiveMQ 以避免连续轮询。 我做了两种处理程序SenderReceiver。它们都有ConnectionFactory、Connecton、Session。 聊天面板代表聊天室,每个聊天室都是一个 Topic。 (当您打开带有选择“房间”的聊天面板时,您在逻辑上订阅了给定的主题。)面板实现了 MessageListener 接口,因此面板是 Receiver 对象中消费者的侦听器。

因此,面板将消息发送到其 Sender 对象中的主题,并通过其 Receiver 对象监听它们。 (是的,每个面板都有一个Sender 和一个Receiver 对象)

这样,每个面板有 2 个连接,根本没有人关心关闭这些连接。 :(

我认为这不是使用 activemq 的好方法。我需要一些建议来实现这个功能。能否请教一下,高手是怎么做的?或者也许我必须去哪个方向?

(ps,AMQ 完全独立运行)

发件人,

public class Sender {

    private String user = ActiveMQConnection.DEFAULT_USER;
    private String password = ActiveMQConnection.DEFAULT_PASSWORD;
    private String url = "failover://(tcp://0.0.0.0:61616)?randomize=false";

    private Destination destination;
    private Connection connection = null;
    private Session session = null;
    private ActiveMQConnectionFactory connectionFactory;
    private MessageProducer producer;

    public Sender(String topicId) {
        try {
            connectionFactory = new ActiveMQConnectionFactory(user, password, url);
            connectionFactory.setDispatchAsync(false);

            connection = connectionFactory.createTopicConnection(user, password);
            connection.start();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createTopic(topicId);

            producer = session.createProducer(destination);
        } catch (JMSException ex) {
            Logger.getLogger(Sender.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println(ex.toString());
        }
    }

    public void sendMessage(String message) {
        try {
            BytesMessage message = session.createBytesMessage();
            message.setLongProperty("text", message);
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            producer.send(destination, message);
        } catch (JMSException ex) {
            Logger.getLogger(Sender.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void close() {
        try {
            producer.close();
            session.close();
            connection.close();
        } catch (JMSException ex) {
            Logger.getLogger(Sender.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

接收者,

public class Receiver {
    private String url = "failover://(tcp://0.0.0.0:61616)?randomize=false";

    private ActiveMQConnectionFactory connectionFactory;
    private Connection connection;
    private Session session = null;
    private Topic destination = null;
    private TopicSubscriber consumer;
    private IdGenerator clientIdGenerator = new IdGenerator();

    public Receiver(String topicId, MessageListener listener) {
        try {
            connectionFactory = new ActiveMQConnectionFactory(url);
            connectionFactory.setDispatchAsync(false);

            connection = connectionFactory.createTopicConnection();
            connection.setClientID(clientIdGenerator.generateId());
            connection.start();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            destination = session.createTopic(topicId);
            consumer = session.createDurableSubscriber(destination, "subscriber");
            consumer.setMessageListener(listener);
        } catch (JMSException ex) {
            Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void close() {
        try {
            consumer.close();
            session.close();
            connection.close();
        } catch (JMSException ex) {
            onException(ex);
            Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

【问题讨论】:

    标签: java wicket activemq


    【解决方案1】:

    要创建聊天面板,我想使用某种 JMS,例如 示例 Apache ActiveMQ 以避免连续轮询。

    您描述的设置仍然需要连续轮询!您的 ChatPanel 是服务器端 Wicket 组件。您仍然需要从这些服务器端 Wicket 组件获取聊天数据到客户端(浏览器),这需要通过 Javascript 进行持续轮询。你可以实现你自己的 Wicket 行为来做到这一点,但它仍然是轮询。

    如果您想完全避免连续轮询,则必须使用 WebSockets。 Wicket 有一个用于 websocket 支持的实验模块 (https://cwiki.apache.org/confluence/display/WICKET/Wicket+Native+WebSockets)。但是,websocket 不适用于旧版浏览器。

    【讨论】:

    • 所以我可以离开 AMQ 并使用 new AbstractAjaxTimerBehavior(Duration.milliseconds(300)){ @Override protected void onTimer(AjaxRequestTarget art){}});查看新消息?
    • 我想如果 TopicSubscriber 有 MessageListener,它会在新消息到达时收到通知,这就是所有的通信。我的 onMessage(Message message)(MessageListener 的方法)在发送消息时从 Topic 获取消息。
    • 是的,当有新消息到达时,您的订阅者会收到通知。但是您无法将此消息从您的 ChatPanel 发送到用户浏览器。在您的评论中使用 AbstractAjaxTimerBehavior 的方式肯定会奏效!但是你必须知道浏览器会轮询你的服务器。
    • 我将消息存储在数据存储中,并且 activeMQ 消息仅包含 DBMessage 的 id,因此在 onMessage(Message message) 中我可以通过数据库中的 id 找到 DBMessage,并且我可以通过 AjaxReqeuestTarget 以某种方式刷新检票口页面跨度>
    • 总结一下,您是否建议离开AMQ并使用TimerBehavior?为什么我必须知道浏览器会轮询我的服务器?解决这种情况的最佳方法是什么?
    猜你喜欢
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 2018-01-28
    • 2015-03-10
    相关资源
    最近更新 更多