一.何为消息中间件?
消息中间件利用高效可靠的消息传递机制,可以在分布式环境下扩展进程间的通信。
意义:
如上图,一个managerweb服务器,关联pageservice服务器只是为了使用生成h静态页面的功能,关联searchService服务器只是为了使用其solr索引库中的内容,但却增加了这么多的依赖,这就极大地提高了代码的耦合度,耦合越多,后期的维护成本也就越高。我们就可以使用消息中间件activeMQ,使运营商系统和搜索服务,页面生成服务解除了耦合。
activeMq的名词解释:
工作模式:点对点订阅,一个发送者一个接受者一一对应。
发布订阅消息模式,一个发送者可以有多个接受者。
工作角色:消息生产者(producer)产生消息,只负责发送
消息消费者(customer)消费消息,只负责监听处理消息
两个小demo,了解基本语法
创建连接工厂对象
获取连接
连接开启
创建会话
创建发送消息的生产者
发送消息
释放资源
-----------------------生产者-------------------
// 创建连接工厂对象 协议使用是tcp协议 端口号换成61616
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("tcp://个人ip:61616");
// 获取连接
Connection connection = connectionFactory.createConnection();
// 连接开启
connection.start();
// 创建会话 参数1boolean类型表示是否支持事务 参数2表示事务的提交方式
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建发送消息的生产者 参数是Destination 目标 目的地
Destination destination = new ActiveMQQueue("queue_test");
MessageProducer producer = session.createProducer(destination);
// 发送消息
Message message = session.createTextMessage("第一个测试的文本消息");
producer.send(message);
// 释放资源
producer.close();
session.close();
connection.close();
-----------------------消费者-------------------
// 创建连接工厂对象 协议使用是tcp协议 端口号换成61616
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("tcp://个人IP:61616");
// 获取连接
Connection connection = connectionFactory.createConnection();
// 连接开启
connection.start();
// 创建会话 参数1boolean类型表示是否支持事务 参数2表示事务的提交方式
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建发送消息的生产者 参数是Destination 目标 目的地
Destination destination = new ActiveMQQueue("queue_test");
//创建消费消息的对象
MessageConsumer consumer = session.createConsumer(destination);
//消费对象监听队列中是否存在未消费的数据
consumer.setMessageListener(new MessageListener() {
//处理消息的方法
public void onMessage(Message message) {
//取出消息队列中未被处理的消息
ActiveMQTextMessage textMessage = (ActiveMQTextMessage)message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
下面说一下实际中的使用,以笔者的项目为例
上面说了,managerWeb依赖太多,耦合性太高,就先对他进行改造,首先把他作为生产者。
1.配置文件applicationContext-jms.xml的编写:
<bean id="mQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg name="brokerURL" value="tcp://192.168.188.131:61616"></constructor-arg>
</bean>
<!--spring管理的连接工厂-->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="mQConnectionFactory"></property>
</bean>
<!--初始化一个发送的队列-->
<bean id="solr_queue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="solr_queue"></constructor-arg>
</bean>
<!--发送消息和消费消息的模板对象-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
2.引入pom依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.14.5</version>
</dependency>
3.在controller中引入 模板和目的队列的属性
@Autowired
private JmsTemplate jmsTemplate;
@Autowired
private Destination solr_queue;
4.在updateStatus的方法中 调用模板的发送
//使用消息队列将list集合传输到activeMQ
jmsTemplate.send(solr_queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
//将所有需要被传输的文本集合 转成文字传输
String itemListStr = JSON.toJSONString(itemList);
return session.createTextMessage(itemListStr);
}
});
将search_service作为消费者
1.引入依赖
2.配置文件
<context:component-scan base-package="com.offcn.search.service.listener"></context:component-scan>
<!--初始化active使用的连接工厂-->
<bean id="mQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg name="brokerURL" value="tcp://192.168.188.131:61616"></constructor-arg>
</bean>
<!--spring管理的连接工厂-->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="mQConnectionFactory"></property>
</bean>
<!--初始化一个发送的队列-->
<bean id="solr_queue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="solr_queue"></constructor-arg>
</bean>
<!--消费消息运行监听器的容器对象-->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="solr_queue"></property>
<property name="messageListener" ref="solrListener"></property>
</bean>
3.创建一个监听器 添加spring的注解 支持扫描
@Service(spring中的service注解)
public class SolrListener implements MessageListener {
@Autowired
private SolrTemplate solrTemplate;
@Override
public void onMessage(Message message) {
//获取集合的字符串
try {
String itemStr = ((ActiveMQTextMessage)message).getText();
List<TbItem> itemList = JSON.parseArray(itemStr,TbItem.class);
//遍历集合存储到sorl索引库
for(TbItem item:itemList){
Map newMap = new HashMap();
//循环的每个item种的spec字符串 转换成map用于生成多个动态域字段 {网络:2G,内存 15g}
Map map = JSON.parseObject(item.getSpec(),Map.class);
//获取规格map种的key 中文
Set<String> set = map.keySet();
for(String key:set){
newMap.put(Pinyin.toPinyin(key,"").toLowerCase(),map.get(key));
}
item.setSpecMap(newMap);
}
solrTemplate.saveBeans(itemList);
solrTemplate.commit();
System.out.println("-------solr--queue-----save success-------");
} catch (JMSException e) {
e.printStackTrace();
}
}
}
总之大白话解释来说就是:就是你的请求需要一个什么样的功能,就将使用一个生产者将消息发送出去,同时再对应的服务器模块中做一个消费者,用来接收消息,并且完成任务,达到实现最终的功能,并且降低了依赖。
综上,over。