编写一个与JMS(ActiveMQ)和OnMessage对话的Servlet更新站点
我正在构建一个站点,该站点使用简单的AJAX Servlet进行JMS(ActiveMQ)对话,并从主题到达消息以更新站点。
我有创建数据的XMLHttpRequest的Javascript。 Servlet处理Get Request并发送回JSON。但是我不知道如何将Servlet连接到ActiveMQ Message Broker。它只是立即发送回伪数据。
我认为Servelt应该实施messagelistener。然后onMessage将数据发送到JavaScript页面。但是我不确定该怎么做。
解决方案
回答
我们可能需要从JNDI获取JMS连接,如下所示:
Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); props.setProperty(Context.PROVIDER_URL, "tcp://hostname:61616"); javax.naming.Context ctx = new InitialContext(props); // lookup the connection factory javax.jms.TopicConnectionFactory factory = (javax.jms.TopicConnectionFactory)ctx.lookup("ConnectionFactory"); // create a new TopicConnection for pub/sub messaging javax.jms.TopicConnection conn = factory.getTopicConnection(); // lookup an existing topic javax.jms.Topic mytopic = (javax.jms.Topic)ctx.lookup("MyTopic"); // create a new TopicSession for the client javax.jms.TopicSession session = conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); // create a new subscriber to receive messages javax.jms.TopicSubscriber subscriber = session.createSubscriber(mytopic);
回答
使用servlet实现MessageListener的问题在于servlet是同步的,而MessageListeners是异步的。相反,我们应该创建一些其他对象来充当MessageListener,并在收到消息时更新某个位置的某个状态(可能是数据库,JMX MBean或者有状态会话EJB)。然后Servlet可以查询该状态以查看是否有要报告的数据回到客户端,网页可以定期对Servlet进行ping操作,以请求新数据。
回答
我们是否尝试过阅读有关此问题的答案,这些答案已链接到ActiveMQ Ajax支持。 ActiveMQ基本上对Ajax具有本机支持,因此我们可以使用其JavaScript库直接从ActiveMQ主题进行订阅。
另请参阅ActiveMQ Web示例,该示例演示如何使用带有ActiveMQ的Ajax进行实时聊天或者实时股票投资组合屏幕
回答
正如James Strachan所说,http://activemq.apache.org/ajax.html是解决我们问题的理想的即用型解决方案。
如果我们仍然想手动创建这样的解决方案,则只需在Ajax servlet中创建JMS连接(每个请求的连接)。因此,考虑使用Spring JMS模板(http://static.springsource.org/spring/docs/2.5.x/reference/jms.html)。然后只需在Servlet doGet / doPost方法中接收消息即可。在这种情况下,请考虑较低的超时值以进行接收。这种解决方案适用于队列和持久性主题。
对于非持久性主题,请考虑使用外部消息侦听器。 SpringMessageListenerContainer
是用于此目的的出色工具:
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer <property name="connectionFactory" ref="jmsFactory"/> <property name="destination" ref="myTopic" /> <property name="messageListener" ref="lastTenUpdatesCache" /> </bean>
BeanlastTenUpdatesCache
将是实现MesssageListener
的单例bean。该bean将负责缓存最后十条消息(只需将其放入java.util列表中)。它将被注入到Ajax servlet中,因此在doGet / doPost方法中,我们可以询问有关发送给该主题的最后10条消息。