实战Spring4+ActiveMQ整合实现消息队列(生产者+消费者)
引言:
最近公司做了一个以信息安全为主的项目,其中有一个业务需求就是,项目定时监控操作用户的行为,对于一些违规操作严重的行为,以发送邮件(FoxMail)的形式进行邮件告警,可能是多人,也可能是一个人,第一次是以单人的形式,,直接在业务层需要告警的地方发送邮件即可,可是后边需求变更了,对于某些告警邮件可能会发送多人,这其中可能就会有阻塞发邮件的可能,直到把所有邮件发送完毕后再继续做下边的业务,领导说这样会影响用户体验,发邮件的时候用户一直处于等待状态,不能干别的事情。最后研究说用消息队列,当有需要发送邮件告警的时候,就向队列中添加一个标识消息,ActiveMQ通过监听器的形式,实时监听队列里边的小时,收到消息后,判断是不是需要发送告警的标识,是的话就自行就行发送邮件!这是就研究的消息队列ActiveMQ,下边就是具体内容:
1. ActiveMQ
1.1). ActiveMQ
ActiveMQ是Apache所提供的一个开源的消息系统,完全采用Java来实现,因此,它能很好地支持J2EE提出的JMS(Java Message Service,即Java消息服务)规范。JMS是一组Java应用程序接口,它提供消息的创建、发送、读取等一系列服务。JMS提供了一组公共应用程序接口和响应的语法,类似于Java数据库的统一访问接口JDBC,它是一种与厂商无关的API,使得Java程序能够与不同厂商的消息组件很好地进行通信。
1. 2). Java Message Service(JMS)
JMS支持两种消息发送和接收模型。
一种称为P2P(Ponit to Point)模型(点对点一对一),即采用点对点的方式发送消息。P2P模型是基于队列的,消息生产者发送消息到队列,消息消费者从队列中接收消息,队列的存在使得消息的异步传输称为可能,P2P模型在点对点的情况下进行消息传递时采用。
另一种称为Pub/Sub(Publish/Subscribe,即发布-订阅)模型,发布-订阅模型定义了如何向一个内容节点发布和订阅消息,这个内容节点称为topic(主题)。主题可以认为是消息传递的中介,消息发布这将消息发布到某个主题,而消息订阅者则从主题订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布-订阅模型在消息的一对多广播时采用。
1.3). JMS术语
- Provider/MessageProvider:生产者
- Consumer/MessageConsumer:消费者
- PTP:Point To Point,点对点通信消息模型
- Pub/Sub:Publish/Subscribe,发布订阅消息模型
- Queue:队列,目标类型之一,和PTP结合
- Topic:主题,目标类型之一,和Pub/Sub结合
- ConnectionFactory:连接工厂,JMS用它创建连接
- Connnection:JMS Client到JMS Provider的连接
- Destination:消息目的地,由Session创建
- Session:会话,由Connection创建,实质上就是发送、接受消息的一个线程,因此生产者、消费者都是Session创建的
1.4). ActiveMQ应用场景
类似送快递,快递员(producer)将快递(Message)放到指定地点(destination)后,就可以离开了,拿快递的人(customer)在接收到通知后,到指定地点(destination)去取快递(Message)就可以了。当然,取快递时可能要进行身份验证,这就涉及到创建连接(connection)时,需要指定用户名和密码了。还有就是,实际生活中,当快递员把快递放好之后,照理说应该通知客户去哪里取快递,而ActiveMq帮我们做好了一切,通知的工作Activemq会帮我们实现,而无需我们亲自编码通知消费者,生产者只需要将Message放到Mq中即可,通知消费者的工作,mq会帮我们处理
用途就是用来处理消息,也就是处理JMS的。消息队列在大型电子商务类网站,如京东、淘宝、去哪儿等网站有着深入的应用,队列的主要作用是消除高并发访问高峰,加快网站的响应速度。
在不使用消息队列的情况下,用户的请求数据直接写入数据库,高发的情况下,会对数据库造成巨大的压力,同时也使得系统响应延迟加剧,但使用队列后,用户的请求发给队列后立即返回。
1.5). ActiveMQ下载
1.6). 启动
/apache-activemq-5.15.3/bin/win64/
目录下双击activemq.bat文件,在浏览器中输入http://localhost:8161/admin/
, 用户名和密码输入admin
即可
2. Srping+ActiveMQ应用实例
2,1). 项目结构
2,2). 导入maven依赖,pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<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> <groupId>www.cnblogs.com.hongmoshu</groupId>
<artifactId>test_actmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>test_actmq Maven Webapp</name>
<url>http://www.example.com</url> <!-- 版本管理 -->
<properties>
<springframework>4.1.8.RELEASE</springframework>
</properties> <dependencies> <!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency> <!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
<version>2.5</version>
</dependency> <!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${springframework}</version>
</dependency> <!-- xbean 如<amq:connectionFactory /> -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency> <!-- activemq -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.12.1</version>
</dependency> <!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.7.1</version>
</dependency> <!-- JSON -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency> </dependencies> <build>
<finalName>test_actmq</finalName> </build>
</project>
2,3). ActiveMQ的配置文件ActiveMQ.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd"
> <context:component-scan base-package="com.svse.service" />
<mvc:annotation-driven /> <!-- jms.useAsyncSend=true 允许异步接收消息 -->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://192.168.6.111:61616?jms.useAsyncSend=true"
userName="admin"
password="admin" /> <!-- 配置JMS连接工 厂 -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="sessionCacheSize" value="100" />
</bean> <!-- 定义消息队列名称(Queue) -->
<bean id="demoQueueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<!-- 设置消息队列的名字 -->
<constructor-arg>
<value>Jaycekon</value>
</constructor-arg>
</bean> <!-- 配置JMS模板(Queue),Spring提供的JMS工具类,它发送、接收消息。 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="demoQueueDestination" />
<property name="receiveTimeout" value="10000" />
<!-- true是topic,false是queue,默认是false,此处显示写出false -->
<property name="pubSubDomain" value="false" />
<!-- 消息转换器 -->
<property name="messageConverter" ref="userMessageConverter"/>
</bean> <!-- 类型转换器 -->
<bean id="userMessageConverter" class="com.svse.util.ObjectMessageConverter"/> <!-- 配置消息队列监听者(Queue) -->
<bean id="queueMessageListener" class="com.svse.util.QueueMessageListener" /> <!-- 显示注入消息监听容器(Queue),配置连接工厂,监听的目标是demoQueueDestination,监听器是上面定义的监听器 -->
<bean id="queueListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="demoQueueDestination" />
<property name="messageListener" ref="queueMessageListener" />
</bean> </beans>
2,4). Spring的配置文件 spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <context:component-scan base-package="com.svse.controller" />
<mvc:annotation-driven />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean> </beans>
2,5). web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>mydemo</display-name> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <!-- 加载spring及active的配置文件,classpath为项目src下的路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-mvc.xml;
classpath:ActiveMQ.xml;
</param-value>
</context-param> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- 处理编码格式 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> </web-app>
2,6). 实体类Users对象
package com.svse.entity;
import java.io.Serializable; public class Users implements Serializable{ private String userId;
private String userName;
private String sex;
private String age;
private String type; public Users() {
super();
}
public Users(String userId, String userName, String sex, String age,
String type) {
super();
this.userId = userId;
this.userName = userName;
this.sex = sex;
this.age = age;
this.type = type;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Users [userId=" + userId + ", userName=" + userName + ", sex="
+ sex + ", age=" + age + ", type=" + type + "]";
} }
2,7). 核心代码(生产者ProducerService)
package com.svse.service; import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session; import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service; import com.svse.entity.Users; @Service
public class ProducerService { @Resource(name="jmsTemplate")
private JmsTemplate jmsTemplate; /**
* 向指定队列发送消息 (发送文本消息)
*/
public void sendMessage(Destination destination,final String msg){ jmsTemplate.setDeliveryPersistent(true); System.out.println(Thread.currentThread().getName()+" 向队列"+destination.toString()+"发送消息---------------------->"+msg);
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(msg);
}
});
} /**
* 向指定队列发送消息以对象的方式 (发送对象消息)
*/
public void sendMessageNew(Destination destination,Users user){
System.out.println(Thread.currentThread().getName()+" 向队列"+destination.toString()+"发送消息---------------------->"+user);
jmsTemplate.convertAndSend(user);
} /**
* 向默认队列发送消息
*/
public void sendMessage(final String msg){
String destination = jmsTemplate.getDefaultDestinationName();
System.out.println(Thread.currentThread().getName()+" 向队列"+destination+"发送消息---------------------->"+msg);
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(msg);
}
});
}
}
2,8). 核心代码(消费产者ConsumerService)
package com.svse.service; import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage; import net.sf.json.JSONObject; import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service; import com.svse.entity.Users; @Service
public class ConsumerService { @Resource(name="jmsTemplate")
private JmsTemplate jmsTemplate;
//接收文本消息
public TextMessage receive(Destination destination){
TextMessage textMessage = (TextMessage) jmsTemplate.receive(destination);
try{
JSONObject json=JSONObject.fromObject(textMessage.getText());
System.out.println("name:"+json.getString("userName"));
System.out.println("从队列" + destination.toString() + "收到了消息:\t"
+ textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
return textMessage;
}
//接收对象消息
public ObjectMessage receiveNew(Destination destination){
ObjectMessage objMsg=(ObjectMessage) jmsTemplate.receive(destination);
try{
Users users= (Users) objMsg.getObject();
System.out.println("name:"+users.getUserName());
System.out.println("从队列" + destination.toString() + "收到了消息:\t"
+ users);
} catch (JMSException e) {
e.printStackTrace();
}
return objMsg;
}
}
2,9). 核心代码(控制器ConsumerService)
package com.svse.controller.mq; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.annotation.Resource;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.google.gson.Gson;
import com.svse.entity.Users;
import com.svse.service.ConsumerService;
import com.svse.service.ProducerService; @Controller
public class DemoController { //队列名Jaycekon (ActiveMQ中设置的队列的名称)
@Resource(name="demoQueueDestination")
private Destination demoQueueDestination; //队列消息生产者
@Resource(name="producerService")
private ProducerService producer; //队列消息消费者
@Resource(name="consumerService")
private ConsumerService consumer; /*
* 准备发消息
*/
@RequestMapping(value="/producer",method=RequestMethod.GET)
public ModelAndView producer(){
System.out.println("------------go producer"); Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = dateFormat.format( now );
System.out.println(time); ModelAndView mv = new ModelAndView();
mv.addObject("time", time);
mv.setViewName("producer");
return mv;
} /*
* 发消息
*/
@RequestMapping(value="/onsend",method=RequestMethod.POST)
public ModelAndView producer(@RequestParam("message") String message) {
System.out.println("------------send to jms");
ModelAndView mv = new ModelAndView();
for(int i=0;i<5;i++){
try {
Users users=new Users("10"+(i+1),"赵媛媛"+(i+1),"女","27","影视演员");
Gson gson=new Gson();
String sendMessage=gson.toJson(users);
System.out.println("发送的消息sendMessage:"+sendMessage.toString());
// producer.sendMessage(demoQueueDestination,sendMessage.toString());//以文本的形式
producer.sendMessageNew(demoQueueDestination, users);//以对象的方式 } catch (Exception e) {
e.printStackTrace();
}
}
mv.setViewName("index");
return mv;
}
/*
* 手动接收消息
*/
@RequestMapping(value="/receive",method=RequestMethod.GET)
public ModelAndView queue_receive() throws JMSException {
System.out.println("------------receive message");
ModelAndView mv = new ModelAndView(); //TextMessage tm = consumer.receive(demoQueueDestination);//接收文本消息 ObjectMessage objMsg=consumer.receiveNew(demoQueueDestination);//接收对象消息
Users users= (Users) objMsg.getObject();
//mv.addObject("textMessage", tm.getText());
mv.addObject("textMessage", users.getUserId()+" || "+users.getUserName());
mv.setViewName("receive");
return mv;
} /*
* ActiveMQ Manager Test
*/
@RequestMapping(value="/jms",method=RequestMethod.GET)
public ModelAndView jmsManager() throws IOException {
System.out.println("------------jms manager");
ModelAndView mv = new ModelAndView();
mv.setViewName("index"); JMXServiceURL url = new JMXServiceURL("");
JMXConnector connector = JMXConnectorFactory.connect(url);
connector.connect();
MBeanServerConnection connection = connector.getMBeanServerConnection(); return mv;
} }
3. 对象转换器MessageConverter和消息监听器MessageListener
在上边的ProducerService和ConsumerService中,不论是发送消息还是接收消息,都可以以文本TextMessage的方式和ObjectMessage的方式.如果是简单的文本消息可以以TextMessage,但是如果需要发送的内容比较多,结构比较复杂,这时候就建议用对象文本ObjectMessage的方式向队列queue中发送消息了.但是这时候就需要用到对象消息转换器MessageConverter.
3,1). 消息转换器MessageageConverte
MessageConverter的作用主要有两方面,一方面它可以把我们的非标准化Message对象转换成我们的目标Message对象,这主要是用在发送消息的时候;另一方面它又可以把我们的Message对象
转换成对应的目标对象,这主要是用在接收消息的时候。
package com.svse.util; import java.io.Serializable; import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session; import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter; /**
*功能说明:通用的消息对象转换类
*@author:zsq
*create date:2019年7月12日 上午9:28:31
*修改人 修改时间 修改描述
*Copyright (c)2019北京智华天成科技有限公司-版权所有
*/
public class ObjectMessageConverter implements MessageConverter { //把一个Java对象转换成对应的JMS Message (生产消息的时候)
public Message toMessage(Object object, Session session)
throws JMSException, MessageConversionException { return session.createObjectMessage((Serializable) object);
} //把一个JMS Message转换成对应的Java对象 (消费消息的时候)
public Object fromMessage(Message message) throws JMSException,
MessageConversionException {
ObjectMessage objMessage = (ObjectMessage) message;
return objMessage.getObject();
} }
注意:写了消息转化器之后还需要的ActiveMQ.xml中进行配置
3,2). 消息监听器MessageageListe
MessageageListe作用就是动态的自行监听消息队列的生产者发送的消息,不需要人工手动接收!
package com.svse.util;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage; import com.svse.entity.Users; public class QueueMessageListener implements MessageListener { //添加了监听器,只要生产者发布了消息,监听器监听到有消息消费者就会自动消费(获取消息)
public void onMessage(Message message) {
//(第1种方式)没加转换器之前接收到的是文本消息
//TextMessage tm = (TextMessage) message; //(第2种方式)加了转换器之后接收到的ObjectMessage对象消息
ObjectMessage objMsg=(ObjectMessage) message;
Users users;
try {
users = (Users) objMsg.getObject();
//System.out.println("QueueMessageListener监听到了文本消息:\t" + tm.getText());
System.out.println("QueueMessageListener监听到了文本消息:\t" + users);
//do something ...
} catch (JMSException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} }
同样写好监听器后也是需在ActiveMQ.xml中进行配置注册的
小结
(1)注册JmsTemplate时,pubSubDomain这个属性的值要特别注意。默认值是false,也就是说默认只是支持queue模式,不支持topic模式。但是,如果将它改为true,则不支持queue模式。因此如果项目需要同时支持queue和topic模式,那么需要注册2个JmsTemplate,同时监听容器(<jms:listener-container>)也需要注册2个
(2)使用Queue时,生产者只要将Message发送到MQ服务器端,消费者就可以进行消费,而无需生产者程序一直运行;
(3)消息是按照先入先出的顺序,一旦有消费者将Message消费,该Message就会从MQ服务器队列中删去;
(4)有文章说,“生产者”<-->"消费者"是一对一的关系,其实并不准确,从应用中可以看出,一个生产者产生的消息,可以被
至此,消息队列ActiveMQ就讲解完了,发送消息和接收消息的页面在此不没贴出来了,如疑问或是更好的方式方法的朋友,欢迎留言一起讨论!
实战Spring4+ActiveMQ整合实现消息队列(生产者+消费者)的更多相关文章
- springBoot(11)---整合Active消息队列
Springboot整合Active消息队列 简单理解: Active是Apache公司旗下的一个消息总线,ActiveMQ是一个开源兼容Java Message Service(JMS) 面向消息的 ...
- php 利用activeMq+stomp实现消息队列
php 利用activeMq+stomp实现消息队列 一.activeMq概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J ...
- #queue队列 #生产者消费者模型
#queue队列 #生产者消费者模型 #queue队列 #有顺序的容器 #程序解耦 #提高运行效率 #class queue.Queue(maxsize=0) #先入先出 #class queue.L ...
- java 动态增加应用服务器,出现的消息队列的消费者提报错问题
java 动态增加应用服务器,出现的消息队列的消费者提报错问题 在项目中,有这样的业务场景,在某一个时间段,客户流量瞬间增大,服务器瞬间很大,出现高并发问题.有一种解决方案就是脚本动态增加业务服务器, ...
- ActiveMq C#客户端 消息队列的使用(存和取)
1.准备工具 VS2013Apache.NMS.ActiveMQ-1.7.2-bin.zipapache-activemq-5.14.0-bin.zip 2.开始项目 VS2013新建一个C#控制台应 ...
- C#实战Microsoft Messaging Queue(MSMQ)消息队列(干货)
前言 在使用MSMQ之前,我们需要自行安装消息队列组件!(具体安装方法大家自己搜一下吧) 采用MSMQ带来的好处是:由于是异步通信,无论是发送方还是接收方都不用等待对方返回成功消息,就可以执行余下的代 ...
- 【ActiveMQ】持久化消息队列的三种方式
1.ActiveMQ消息持久化方式,分别是:文件.mysql数据库.oracle数据库 2.修改方式: a.文件持久化: ActiveMQ默认的消息保存方式,一般如果没有修改过其他持久化方式的话可以不 ...
- RabbitMQ消息队列生产者和消费者
概述 生产者生产数据至 RabbitMQ 队列,消费者消费 RabbitMQ 队列里的数据. 详细 代码下载:http://www.demodashi.com/demo/10723.html 一.准备 ...
- C#实战Microsoft Messaging Queue(MSMQ)消息队列
前言 在使用MSMQ之前,我们需要自行安装消息队列组件!(具体安装方法大家自己搜一下吧) 采用MSMQ带来的好处是:由于是异步通信,无论是发送方还是接收方都不用等待对方返回成功消息,就可以执行余下的代 ...
随机推荐
- wpf 高DPI开发
https://blog.walterlv.com/post/windows-high-dpi-development.html https://blog.csdn.net/ZslLoveMiwa/a ...
- texbox 禁用copy paster cut
<TextBox CommandManager.PreviewExecuted="textBox_PreviewExecuted" ContextMenu="{x: ...
- Linux学习之“exit函数”
先看下"_exit"和"exit": exit被调用时,将冲刷所有的标准I/O流,关闭所有打开的文件描述符.在传统实现中,同时也将关闭标准I/O流.即表示标准输 ...
- Win8Metro(C#)数字图像处理--2.28图像乘法运算
原文:Win8Metro(C#)数字图像处理--2.28图像乘法运算 [函数名称] 图像乘法函数MultiplicationProcess(WriteableBitmap src, Writea ...
- Redis实现Timeline
上回写了[使用Redis实现关注关系][1],这次说说使用Redis实现Timeline. Timeline的实现一般有推模式.拉模式.推拉结合这几种. 推模式:某人发布内容之后推送给所有粉丝,空间换 ...
- 微信小程序把玩(三十五)Video API
原文:微信小程序把玩(三十五)Video API 电脑端不能测试拍摄功能只能测试选择视频功能,好像只支持mp4格式,值得注意的是成功之后返回的临时文件路径是个列表tempFilePaths而不是tem ...
- Android Studio 添加 Genymotion插件
原文:Android Studio 添加 Genymotion插件 1.下载Genymotion:官网地址,必须先注册才能下载,下载带有VirtualBox的版本 2.安装:安装时会连VirtualB ...
- EasyUI之combogrid
html代码: <div class="item-label">@Html.L("Name"):</div> <input id= ...
- 为什么360、百度、腾讯出的Mac端云盘客户端都只有同步盘?(用户量小,同步盘开发成本低,Linux下都没有客户端)
如题,顾名思义,同步盘是用来同步的,不具备增量的功能,像这三家在Windows端出的客户端都是即有同步也有增量的. 陆续出来的,可能大家更多的是跟随策略,不得不提dropbox是这样的形式.mac电脑 ...
- scrapy爬虫框架研究!
最近由于项目需要,开始研究scrapy爬虫,走过不少弯路,准备写个记录,记下踩过的各种坑.