最近公司的项目里有需要服务端向web端实时推送消息的需求,网上搜索了一番,有前端页面通过定时任务向后台发送ajax请求刷新,有使用第三方提供的消息服务(GoEasy),前者因为会有很多请求是无用的,容易加大服务器负荷造成宕机,后者现在收费了(免费的也只能用一年并且使用上有所限制)。后来在网上看到activemq可以通过ajax请求访问订阅消息,于是便想到用activemq来实现此功能并记录下来,供自己以及需要帮助的程序员朋友参考学习。
1. 我项目使用的spring boot并且maven依赖的,下面贴出activemq的maven依赖:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
<version>5.15.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/activemq-broker-5.15.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.15.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/activemq-client-5.15.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-kahadb-store</artifactId>
<version>5.15.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/activemq-kahadb-store-5.15.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
<version>5.15.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/activemq-spring-5.15.2.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>hawtbuf</artifactId>
<version>1.11</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/hawtbuf-1.11.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-web</artifactId>
<version>5.15.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/activemq-web-5.15.2.jar</systemPath>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
</dependency>
这里要说明一下,我这里是把activemq的jar包放在了本地,所以采用这种本地依赖方式。
2. 接着是后台向activemq发送消息的代码:
public class ActiveMQUtil {
/**
* 发送消息至mq
* @param topic 主题
* @param message 消息内容
*/
public static void sendMessage(String topic, String message){
ConnectionFactory connectionFactory;
Connection connection = null;
Session session;
Destination destination;
MessageProducer producer;
// 构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, Const.MQ_BROKEN_URL);
try { // 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.TRUE,
Session.AUTO_ACKNOWLEDGE);
destination = session.createTopic(topic);
// 得到消息生成者【发送者】
producer = session.createProducer(destination);
// 设置不持久化,实际根据项目决定
// producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 构造消息
TextMessage textMsg = session.createTextMessage();
textMsg.setText(message);
producer.send(destination, textMsg);
session.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != connection)
connection.close();
} catch (Throwable ignore) {
}
}
}
}
3 向spring boot中注入activemq处理ajax请求的servlet,代码片段如下:
/**
* 注入activemq的ajax控制器
@Bean
public ServletRegistrationBean ajaxServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new AjaxServlet());
registration.setEnabled(true);
registration.addUrlMappings("/amq/*");
return registration;
}
//向servletContext中初始化activemq的消息访问url
@Bean
public ServletContextInitializer initializer() {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("org.apache.activemq.brokerURL", "tcp://localhost:61616");
}
};
}
4 代码里调用发送消息的工具类方法,比如商品下架了,要给商户发送通知消息:
//msg为topic,可根据项目实际情况自由决定
ActiveMQUtil.sendMessage("msg","您的商品被下架了");
5 前台页面ajax调用:
5.1 先要引入activemq的ajax插件:
由于我使用的是基于jQuery的adapter,所以还要引入jQuery,另外amq_jquery_adapter.js和amq.js在下载的activemq的压缩包中\webapps-demo\demo\js目录下有(ajax功能好像是5.6以后版本才有的)。
<script src="jquery.min.js?v=2.1.4"></script>
<script src="amq_jquery_adapter.js"></script>
<script src="amq.js"></script>
5.2 接着是js调用:
window.onload = function() {
var amq = org.activemq.Amq;
amq.init({ uri: '/amq', logging: false, timeout: 45, clientId:'test1' });
var myHandler ={
rcvMessage: function(message){
//接收到消息后,自己的业务处理逻辑
}
};
amq.addListener('test1','topic://msg',myHandler.rcvMessage);
//test1为消费者的一个ID,接受到消息回调时会用到作为标识
//topic://msg表示主题订阅目的地
};
说明:
uri为前面注入activemq的ajax控制器时定义的访问url;
Clientid表示浏览器的身份,如果用同一个字符串,则只有一个窗口会生效;如果用时间或者登陆的用户id或其他唯一值做参数时,那么每一个浏览器窗口就相当于不同的消费者。
myHandler接收到消息之后的回调函数
以上就是项目中使用activemq进行消息推送接收的代码片段,目前已经在生产环境完美运行,当后台发送消息到activemq时,前端页面都能实时的读取到并执行相应的业务逻辑。