前端获取实时数据探索
背景介绍
最近在工作中,有个需求是前端需要获取实时展示最新的n条报警数据。使用http的请求响应,一问一答方式获取数据时,就出现可能部分数据获取不到的问题,然后在网上寻找和咨询老同事相关解决方案的时
候,发现有使用DWR的方式进行向前端推送的解决方案,
解决思路
1.ajax订阅ActiveMQ
ajax订阅activeMQ获取实时数据的流程如下

使用ajax直接获取ActiveMQ topic中的数据,可以在activeMQ 官网中,找到Demo。需要在相应的页面中引入amq.js,amq_jquery_adapter.js以及jquery-1.4.2.min.js三个js文件,并且在后端添加相应的servlet配置。
demo中给出的配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <servlet> <servlet-name>AjaxServlet</servlet-name> <servlet-class>org.apache.activemq.web.AjaxServlet</servlet-class> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>AjaxServlet</servlet-name> <url-pattern>/amq/*</url-pattern> </servlet-mapping>
<context-param> <param-name>org.apache.activemq.brokerURL</param-name> <param-value>tcp://127.0.0.1:61616</param-value> </context-param>
|
同时我们需要在项目中引入对应版本的activeMQ-web.jar。来提供对订阅MQ的支持,这样在相应页面添加对应的Js订阅代码,就可以实现使用ajax订阅activeMQ topic进行消费的目的。
虽然这样就可以解决问题,但是总觉得将MQ地址直接配置到web.xml中,这种实现方式很不优雅,通过对AjaxServlet以及其父类源码阅读,发现在创建MQ连接的方式有两种,一种是通过获取获取servlet上下文中初始化时添加的全局参数org.apache.activemq.brokerURL,来创建和MQ的连接,就是上面看到的配置文件中的方法,还有一种是从serlvet上下文中获取创建连接的工厂类进行创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public static final String CONNECTION_FACTORY_ATTRIBUTE = "org.apache.activemq.connectionFactory";
protected static synchronized void initConnectionFactory(ServletContext servletContext) { if (factory == null) { factory = (ActiveMQConnectionFactory)servletContext.getAttribute(CONNECTION_FACTORY_ATTRIBUTE); } if (factory == null) { String brokerURL = getInitParameter(servletContext, BROKER_URL_INIT_PARAM);
if (brokerURL == null) { LOG.debug("Couldn't find " + BROKER_URL_INIT_PARAM + " param, trying to find a broker embedded in a local VM"); BrokerService broker = BrokerRegistry.getInstance().findFirst(); if (broker == null) { throw new IllegalStateException("missing brokerURL (specified via " + BROKER_URL_INIT_PARAM + " init-Param) or embedded broker"); } else { brokerURL = "vm://" + broker.getBrokerName(); } }
LOG.debug("Using broker URL: " + brokerURL); String username = getInitParameter(servletContext, USERNAME_INIT_PARAM); String password = getInitParameter(servletContext, PASSWORD_INIT_PARAM); ActiveMQConnectionFactory amqfactory = new ActiveMQConnectionFactory(username, password, brokerURL);
if (servletContext.getInitParameter(CONNECTION_FACTORY_PREFETCH_PARAM) != null) { int prefetch = Integer.valueOf(getInitParameter(servletContext, CONNECTION_FACTORY_PREFETCH_PARAM)).intValue(); amqfactory.getPrefetchPolicy().setAll(prefetch); }
if (servletContext.getInitParameter(CONNECTION_FACTORY_OPTIMIZE_ACK_PARAM) != null) { boolean optimizeAck = Boolean.valueOf(getInitParameter(servletContext, CONNECTION_FACTORY_OPTIMIZE_ACK_PARAM)).booleanValue(); amqfactory.setOptimizeAcknowledge(optimizeAck); }
factory = amqfactory;
servletContext.setAttribute(CONNECTION_FACTORY_ATTRIBUTE, factory); } }
|
从上面源码的ajaxServlet初始化方法中可以看到,首先从servlet的上下文中尝试获取ActiveMQConnectionFactory,如果没有设置则才会从上下文中找brokerURl进行初始化,所以我们可以继承AjaxServlet,然后在继承的servlet的init方法中按照需要创建ActiveMQConnectionFactory实例,然后将工厂实例添加到servlet上下文中供创建MQ连接使用。
2.使用websocket实时获取报警数据
3.websocket订阅ActiveMQ
1)基于stomp协议
2)基于mqtt协议
几种方案分析