ActiveMQ
MQ : Message Queue 就是消息队列
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。
ActiveMQ消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。
主要特点:
1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去
4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
6. 支持通过JDBC和journal提供高速的消息持久化
7. 从设计上保证了高性能的集群,客户端-服务器,点对点
8. 支持Ajax
9. 支持与Axis的整合
10. 可以很容易得调用内嵌JMS provider,进行测试
JMS介绍
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
JMS是一个与具体平台无关的API,具有跨平台性。
它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息。把它应用到实际的业务需求中的话我们可以在特定的时候利用生产者生成一消息,并进行发送,对应的消费者在接收到对应的消息后去完成对应的业务逻辑。
JMS定义了五种不同的消息正文格式:
• StreamMessage -- Java原始值的数据流
• MapMessage--一套名称-值对
• TextMessage--一个字符串对象
• ObjectMessage--一个序列化的 Java对象
• BytesMessage--一个字节的数据流
ActiveMQ安装
ActiveMQ是一个java语言开发的MQ服务器。在安装之前必须安装jdk。使用jdk1.7以上版本。
上传ActiveMQ安装文件
移动到/usr/local中
[root@itcast-01 ~]# mv apache-activemq-5.12.0-bin.tar.gz /usr/local/
解压
进入/usr/local/目录
[root@itcast-01 ~]# cd /usr/local/
解压文件
[root@itcast-01 local]# tar -zxvf apache-activemq-5.12.0-bin.tar.gz
启动ActiveMQ
进入解压后的文件夹的bin/linux-x86-32/目录
[root@itcast-01 local]# cd apache-activemq-5.12.0/bin/linux-x86-32/
启动ActiveMQ
[root@itcast-01 linux-x86-32]# ./activemq start
访问地址:
http://192.168.xx.xx:8161/admin/
账号:admin
密码:admin
页面问题
访问点对点和广播的时候会报错,默认会访问本地的地址,这时候是访问不到的
1.先停止activemq服务,通过命令: [root@itcast-01 linux-x86-32]# ./activemq stop
2.修改host文件: vim /etc/hosts 在后面加上本地地址:itcast-01
之后再启动:
[root@itcast-01 linux-x86-32]# ./activemq start
activeMQ整合spring
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.taotao</groupId> <artifactId>taotao-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.itcast.activemq</groupId> <artifactId>itcast-activemq</artifactId> <version>1.0.0-SNAPSHOT</version> <dependencies> <!-- 加入ActiveMQ依赖 --> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> </dependency> <!-- 加入spring-jms依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> </dependencies>
</project>
广播形式的Spring配置
1.生产者的Spring的配置
applicationContext-activemq.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jms="http://www.springframework.org/schema/jms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.37.161:61616" />
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory" />
</bean>
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<!--这个是主题目的地,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="aa-bb-topic" />
</bean>
</beans>
生产者发送消息
private static final ObjectMapper MAPPER = new ObjectMapper(); // 注入JMSTemplate @Autowired private JmsTemplate jmsTemplate; // 注入Destination @Autowired private Destination destination; // 通用发送消息方法,第一个参数是操作符,第二个参数是商品id private void sendMQ(final String type, final Long itemId) { this.jmsTemplate.send(destination, new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { // 声明消息 TextMessage textMessage = new ActiveMQTextMessage(); // 构建消息内容 // 使用json格式的数据封装需要传递的消息 Map<String, Object> map = new HashMap<>(); // 操作符 map.put("type", type); // 商品id map.put("itemId", itemId); try { // 把map转为接送格式的数据 String json = MAPPER.writeValueAsString(map); // 设置消息内容 textMessage.setText(json); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return textMessage; } }); }
2.生产者的Spring配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 --> <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://192.168.37.161:61616" /> </bean> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> <property name="targetConnectionFactory" ref="targetConnectionFactory" /> </bean> <!--这个是主题目的地,一对多的 aa-bb-topic 是广播对应的名字--> <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg value="aa-bb-topic" /> </bean> <!-- messageListener实现类 自己实现的--> <bean id="MyMessageListener" class="com.aa.search.activemq.MyMessageListener"></bean> <!-- 配置一个jsm监听容器 MyMessageListener 对应自己实现的类ID--> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="topicDestination" /> <property name="messageListener" ref="MyMessageListener" /> </bean> </beans>
消费放接收消息
public class MyMessageListener implements MessageListener { private final static ObjectMapper MAPPER = new ObjectMapper(); @Autowired private SearchService searchService; @Override public void onMessage(Message message) { if (message instanceof TextMessage) { // 获取消息对象 TextMessage textMessage = (TextMessage) message; try { // 获取消息内容 String msg = textMessage.getText(); if (StringUtils.isNotBlank(msg)) { // 解析消息 // 把json转为jsonNode JsonNode jsonNode = MAPPER.readTree(msg); // 获取操作符 String type = jsonNode.get("type").asText(); // 获取商品id long itemId = jsonNode.get("itemId").asLong(); // 更新索引库 this.searchService.saveItem(item); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }