如何在项目中使用Active MQ

Active MQ C#实现 主要以源码的形式介绍如何用C#实现同Active MQ 的通讯。本文假设你已经正确安装JDK1.6.x,了解Active MQ并有一定的编程基础。 阅读详情

对Active MQ的了解、封装和使用

1、了解Active MQ

1.1 什么是消息队列?

在这里插入图片描述
ActiveMQ是Apache所提供的采用Java来实现的开源的消息系统。主要用于流量缓冲、异步解耦、多系统之间的通信以及日志处理等。

1.2 主流消息队列的对比

在这里插入图片描述

1.3 Active MQ的整体结构是怎样的?

Active MQ由三部分组成:生产者、队列、消费者

1.3.1 Active MQ有以下两种队列模式:

  • Queue(队列)模式
    点对点:Queue,不可重复消费。该模式下多个消费者监听同一个队列,每条消息只能由某一个消费者消费一次。
    在这里插入图片描述

  • Topic(通配符)模式
    又称为发布-订阅模型。消息发布这将消息发布到某个主题,而消息订阅者则从主题订阅消息。消息会被投递到所有订阅的消费者,所以一条消息会被多个消费者消费
    在这里插入图片描述

2、简单熟悉Active MQ的可视化管理界面

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3、消息的持久化方式

// 创建一个生产者
MessageProducer producer = session.createProducer(destination);
//设置消息持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
这个持久化是指消息发送到队列,持久化到硬盘,默认是开启的,重启MQ之后,消息依然存在。否则,这个消息只会保存在内存,重启后会丢失。
需要注意的是,在topic模式下,不使用持久化订阅者。即使设置持久化,也没法让订阅者离线后继续接收消息。如果使用持久化订阅者,不使用持久化,则重启后保存在临时队列中的消息丢失。

4、Active MQ 如何保证消息的可靠性

消息的成功消费通常包含三个阶段:客户接收消息、客户处理消息、消息被确认。消息被确认后,消费者无法再次读取,相反如果消息未被确认,则消费者可以一直读取。

	Session javax.jms.Connection.createSession(boolean transacted, int acknowledgeMode) throws JMSException
  • 事务模式
    由transacted参数控制。
  1. transacted 为 true 时:表示事务性会话,此时当一个事务被提交时(调用session.commit()确认消息),确认自动发生。此时与 acknowledgeMode 参数设置无关。

  2. transacted 为 false 时:表示非事务性会话,此时消息何时被确认取决于创建会话时的应答模式(acknowledgeMode)。与 acknowledgeMode 参数有关。

  • ACK应答/确认模式
类型描述
Session.AUTO_ACKNOWLEDGE自动确认。当客户成功的从 receive 方法,或者从 MessageListener.onMessage 方法返回的时候,会话自动确认客户收到的消息。
Session.CLIENT_ACKNOWLEDGE客户确认。客户通过调用消息(Session)的 acknowledge() 方法确认消息。client 确认模式是在会话层上进行,只要确认一个被消费的消息,将自动确认当前会话中所有已经被消费的消息。比如一个会话中消费者消费了10个消息,然后确认了第8个消息,那么这10个消息都会被确认。
Session.DUPS_ACKNOWLEDGE迟钝确认。该模式只是会话迟钝的确认消息的提交。如果 JMS Provider 失败,那么可能会导致一些重复的消息。如果是重复的消息,那么 JMS provider 必须把消息头的 JMSRedelivered 字段设置为 true。不常用。
Session.SESSION_TRANSACTED当transacted为true时,默认就是这种模式,使用事务提交的方式确认消息
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE单条消息确认,这种确认模式,它的确认时机和CLIENT_ACKNOWLEDGE几乎一样,当消息消费成功之后,需要调用message.acknowledege来确认此消息(单条),而CLIENT_ACKNOWLEDGE模式先message.acknowledge()方法将导致整个session中所有消息被确认(批量确认)

5、创建消费者的几种方法

//创建普通消费者
MessageConsumer createConsumer(Destination destination);
MessageConsumer createConsumer(Destination destination, String messageSelector); 
MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal);
//创建持久化订阅消费者
TopicSubscriber createDurableSubscriber(Topic topic, String name);
TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal);

参数解释:
Destination 和 Topic 分别都代表队列。
name:持久化订阅消费者名称。
messageSelector:消息选择器
noLocal:noLocal标志默认为false,当设置为true时限制消费者只能接收和自己相同的连接(Connection)所发布的消息,此标志只适用于主题,不适用于队列

关于消息选择器

消息选择器是用于MessageConsumer的过滤器,可以用来过滤传入消息的属性和消息头部分(但不过滤消息体),并确定是否将实际消费该消息。按照JMS文档的说法,消息选择器是一些字符串,它们基于某种语法,而这种语法是SQL-92的子集。可以将消息选择器作为MessageConsumer创建的一部分。

例如:
public final String SELECTOR = “JMSType = ‘TOPIC_PUBLISHER’”;

该选择器检查了传入消息的JMSType属性,并确定了这个属性的值是否等于TOPIC_PUBLISHER。如果相等,则消息被消费;如果不相等,那么消息会被忽略。


6、在普通java项目中如何使用Active MQ

  • 生产者推送字符串消息:
// 创建一个生产者
MessageProducer producer = session.createProducer(destination);
// 创建map消息
MapMessage mapMessage = session.createMapMessage();
for (Entry<String, String> item : message.entrySet()) {
	mapMessage.setString(item.getKey(), item.getValue());
}
// 发送消息
producer.send(mapMessage);
  • 消费者获取字符串消息:
if (message instanceof MapMessage) {
	final MapMessage mapMessage=(MapMessage) message;
	//取出字符串消息
	 System.out.println("消费的消息client:" + textMessage.getText());
}
  • 生产者推送map消息:
// 创建一个生产者
MessageProducer producer = session.createProducer(destination);
// 创建文本消息
TextMessage message = session.createTextMessage("一条文本消息");
// 发送消息
producer.send(message);
  • 消费者获取map消息:
if (message instanceof MapMessage) {
	final MapMessage mapMessage=(MapMessage) message;
	//取出map消息
	Map<String,String> params = new HashMap<String,String>();
	Enumeration<String> keys = mapMessage.getMapNames();
	while (keys.hasMoreElements()) {
		String key = (String) keys.nextElement();
		String value = mapMessage.getString(key);
		params.put(key, value);
	}
}

添加jar包

<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-all</artifactId>
	<version>5.9.0</version>
</dependency>
<!-- 工具包 -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-lang3</artifactId>
	<version>3.9</version>
</dependency>

Queue模式

消息生产者

package com.study.queue;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 生产者
 */
public class Producer {

	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin","admin");
		// 打开连接
		connection.start();
		// 创建会话
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据,在生产者段,使用哪种确认方式都无所谓
		Destination destination = session.createQueue("myQueue");
		// 创建一个生产者
		MessageProducer producer = session.createProducer(destination);
		// 向队列推送10个文本消息数据
		for (int i = 1; i <= 10; i++) {
			// 创建文本消息
			TextMessage message = session.createTextMessage("第" + i + "个文本消息");
			// 发送消息
			producer.send(message);
			// 在本地打印消息
			System.out.println("已发送的消息:" + message.getText());
		}
		// 关闭连接
		connection.close();
	}
}


消费者(使用非事务、消息自动ACK确认的模式)

  • 使用MessageListener的方式监听消息
package com.study.queue.autoack;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消费者
 */
public class Consumer {

	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin", "admin");
		// 打开连接
		connection.start();
		// 创建会话,自动ACK确认
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据
		Destination destination = session.createQueue("myQueue");
		// 创建消费者
		MessageConsumer consumer = session.createConsumer(destination);
		// 创建消费的监听
		consumer.setMessageListener(new MessageListener() {
			public void onMessage(Message message) {
				TextMessage textMessage = (TextMessage) message;
				try {
					System.out.println("消费的消息:" + textMessage.getText());
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		});

	}
}


  • 使用receive方法阻塞线程,直到接收到消息
package com.study.queue.clientack;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消费者
 */
public class Consumer {

	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin","admin");
		// 打开连接
		connection.start();
		// 创建会话,手动ACK确认
		Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据
		Destination destination = session.createQueue("myQueue");
		// 创建消费者
		MessageConsumer consumer = session.createConsumer(destination);
		// 用阻塞的方式监听队列消息
        while(true)	
        {
        	Message message = consumer.receive();//receive方法会导致当前线程阻塞,直到接收到消息
            if (message instanceof TextMessage) {
            	TextMessage textMessage = (TextMessage) message;//消费者接收消息。因为对方发送的 Map 消息,所以可以强转
                System.out.println("消费的消息client ACK:" + textMessage.getText());
                textMessage.acknowledge();//应答/确认消息
            }
        }
		
	}
}


Topic模式

注意:topic模式必须先启动消费者,否则无法消费启动消费者之前发送的消息

消息生产者

package com.study.topic;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class Producer {
	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin","admin");
		// 打开连接
		connection.start();
		// 创建会话
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据
		Destination destination = session.createTopic("topicTest");
		// 创建一个生产者
		MessageProducer producer = session.createProducer(destination);
		//设置消息持久化,可以不设置,默认就是持久化到硬盘
		producer.setDeliveryMode(DeliveryMode.PERSISTENT);
		// 向队列推送10个文本消息数据
		for (int i = 1; i <= 10; i++) {
			// 创建文本消息
			TextMessage message = session.createTextMessage("第" + i + "个文本消息");
			// 发送消息
			producer.send(message);
			// 在本地打印消息
			System.out.println("已发送的消息:" + message.getText());
		}
		// 关闭连接
		connection.close();
	}
}


消费者

  • 普通订阅者模式(该模式下和Queue的消费者基本一致。只是创建队列的时候使用session.createTopic(“topicTest”))
package com.study.topic;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * topic模式必须先启动消费者,否则无法消费启动消费者之前发送的消息
 */
public class Consumer2 {
	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin","admin");
		// 打开连接
		connection.start();
		// 创建会话
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据
		Destination destination = session.createTopic("topicTest");
		// 创建消费者
		MessageConsumer consumer = session.createConsumer(destination);
		// 创建消费的监听
		consumer.setMessageListener(new MessageListener() {
			@Override
			public void onMessage(Message message) {
				TextMessage textMessage = (TextMessage) message;
				try {
					System.out.println("消费者1的消息:" + textMessage.getText());
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		});
	}
}

  • 持久订阅者模式
    注意:若要持久订阅者在离线后依然可以获取订阅队列的消息
    1、必须先注册持久订阅者,即先启动消费者,在启动生产者。
    2、必须保证订阅者重启后,ClientID、队列名、持久化订阅者名称和离线前注册时一致,如果有一项不一致,则无法获取到消息

    大概原理:持久订阅时,客户端Sub向服务器注册一个自己身份的ID、订阅队列名称和消费者名称,当这个客户端Sub处于离线时,Pub 会为注册的订阅者 保存所有发送到主题的消息,当客户端Sub再次连接到Pub时,会根据自己的注册时的信息得到所有当自己处于离线时发送到主题的消息
package com.study.topic;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * topic 持久订阅者模式,该模式下,订阅者会持久化,当订阅者离线后,该订阅者订阅的Topic的消息会用一个队列存储起来。直到该订阅者上线,就从暂存的队列推送给订阅者。
 * 该模式依然要先启动消费者,先注册持久订阅者,否则依然接收不到注册之前的消息
 * @author yanlei.wb
 *
 */
public class Consumer3 {
	private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";

	public static void main(String[] args) throws JMSException {
		// 创建连接工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
		// 创建连接
		Connection connection = activeMQConnectionFactory.createConnection("admin","admin");
		//连接的id,该id必须唯一,针对于整个MQ服务,只能有一个连接的id为client_id_1
		connection.setClientID("client_id_1");
		// 打开连接
		connection.start();
		// 创建会话
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 创建队列目标,并标识队列名称,消费者根据队列名称接收数据
		Topic topic = session.createTopic("topicTest");
		// 创建消费者
		TopicSubscriber consumer = session.createDurableSubscriber(topic, "consumer_name1");
		// 创建消费的监听
		consumer.setMessageListener(new MessageListener() {
			@Override
			public void onMessage(Message message) {
				TextMessage textMessage = (TextMessage) message;
				try {
					System.out.println("消费者3的消息:" + textMessage.getText());
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		});
	}
}


7、尝试对Active MQ进行封装(暂时仅针对Queue)

1、封装需要实现的效果:

  • 使用客户端确认的方式,消费一条消息未抛出异常时,发送ACK确认消费。
  • 维护Active MQ连接数量根据压力实现动态伸缩,并实现连接的重复利用。
  • 封装发送消息的方法。
  • 抽象出一个消费者抽象类,所有的消费者只需继承该类,重写抽象方法,在方法内实现消费逻辑。
  • 支持配置多线程消费消息。

2、项目git地址


8、在spring中如何使用Active MQ

配置部分

项目公共配置

schema约束:

<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.3.xsd
				        http://www.springframework.org/schema/context
				        http://www.springframework.org/schema/context/spring-context-4.3.xsd
				        http://www.springframework.org/schema/mvc
				        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
				        http://www.springframework.org/schema/jms
				        http://www.springframework.org/schema/jms/spring-jms-4.3.xsd
				        http://activemq.apache.org/schema/core
				        http://activemq.apache.org/schema/core/activemq-core-5.7.0.xsd">
</beans>

properties配置文件读取:

<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>classpath:config.properties</value>
		</list>
	</property>
</bean>

第一步:添加依赖

activeMQ相关依赖:

<dependency>
	<groupId>org.apache.xbean</groupId>
	<artifactId>xbean-spring</artifactId>
	<version>3.16</version>
</dependency>
<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>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jms</artifactId>
	<version>4.3.14.RELEASE</version>
</dependency>

spring相关依赖:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.3.14.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>4.3.14.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-beans</artifactId>
	<version>4.3.14.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-expression</artifactId>
	<version>4.3.14.RELEASE</version>
</dependency>

<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.2</version>
</dependency>
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.6.1</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.6.1</version>
</dependency>

第二步:定义ActiveMQ连接工厂

<!-- ActiveMQ 连接工厂 :真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<amq:connectionFactory id="amqConnectionFactory"
       brokerURL="${activemq.ip}" 	userName="${activemq.username}" password="${activemq.password}"  />

或者

<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> 
		<property name="clientID" value="test.clientID"/>
		<property name="brokerURL" value="${activemq.ip}"/>
		<property name="userName" value="${activemq.username}"/>
		<property name="password" value="${activemq.password}"/>
</bean>  

第三步:使用Spring Caching连接工厂 对第二步的连接工厂进行封装

  • 这样做的目的是提升性能,对sessions, connections 和 producers进行缓存复用,减少开销。
<!-- Spring Caching连接工厂 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->  
    <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
    <!-- Session缓存数量 -->
    <property name="sessionCacheSize" value="100" />
</bean>

第四步:构建JmsTemplate(通过JmsTemplate发送消息到队列)

这里配置了两个JmsTemplate,一个用于发送订阅型消息。一个用于发送队列型消息

<!-- 定义JmsTemplate的Queue类型 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
    <!--构造参数,传入连接工厂对象 -->  
    <constructor-arg ref="connectionFactory" />
    <!-- 非pub/sub模型(发布/订阅),即队列模式 -->
    <property name="pubSubDomain" value="false" />
</bean>

<!-- 定义JmsTemplate的Topic类型 :对于Topic而言,一条消息只有所有的订阅者都消费才会被删除-->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
    <!--构造参数,传入连接工厂对象 -->   
    <constructor-arg ref="connectionFactory" />
    <!-- pub/sub模型(发布/订阅) -->
    <property name="pubSubDomain" value="true" />
</bean>

第五步:定义队列监听器容器(在监听容器中添加消费者)

<!-- 定义Queue监听器(定义消费者) -->
<jms:listener-container destination-type="queue"
	container-type="default" connection-factory="connectionFactory"
	acknowledge="auto">
	<!-- <jms:listener destination="队列名称" ref="消费者bean id"/> -->
	<jms:listener destination="my-queue" ref="MyConsumerQueue1" />
	<jms:listener destination="my-queue" ref="MyConsumerQueue2" />
</jms:listener-container>

<!-- 定义Topic监听器(定义消费者) -->
<jms:listener-container client-id="test.clientID" destination-type="durableTopic"
	container-type="default" connection-factory="connectionFactory"
	acknowledge="auto">
	<!-- <jms:listener destination="队列名称" ref="消费者bean id"/> -->
	<jms:listener subscription="Topic1-Name" destination="my-topic" ref="MyConsumerTopic1" />
	<jms:listener subscription="Topic2-Name" destination="my-topic" ref="MyConsumerTopic2" />
</jms:listener-container>

配置说明:
jms:listener-container:

  • destination-type:
  • container-type:container的类型,值可以是
    default ( DefaultMessageListenerContainer )
    simple (SimpleMessageListenerContainer)
  • connection-factory:连接工厂
  • acknowledge:确认方式

jms:listener:

  • destination:队列名称
  • ref:消费者bean id
  • subscription:持久化订阅者的名称

若使用持久化订阅者,则还需要在第二步配置clientID。可以参考上面的在普通java项目中使用Topic模式时讲到的【持久订阅者模式】。

第六步:配置spring 包扫描

<context:component-scan base-package="com.study"/>

第七步:配置log4j

添加log4j配置文件,不然启动报错

代码部分

第一步:编写消费者代码,

消费者继承MessageListener,并纳入spring容器,将消费者的bean Id在【配置部分】第五步中配置在队列监听容器中。

  • Queue消费者
package com.study.consumer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;

@Component(value="MyConsumerQueue1")
public class MyConsumerQueue1 implements MessageListener {
    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("Queue1收到的信息:" + textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
  • Topic消费者
package com.study.consumer;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.springframework.stereotype.Component;

@Component(value="MyConsumerTopic1")
public class MyConsumerTopic1 implements MessageListener {
    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("Topic1收到的信息:" + textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

第二步:编写消费生产者

消息生产者,简单封装了4个方法,分别是向Queue和Topic这两种模式的队列中发送String消息和Map消息。
需要注意的是,在向这两种模式发送消息的时候使用的JmsTemplate 对象是不同的。这个对象是在在【配置部分】第四步中配置。

package com.study.producer;

import java.util.Map;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;

@Component
public class MessageProducer {

	@Autowired
	@Qualifier("jmsQueueTemplate")
	private JmsTemplate queuejmsTemplate;
	
	@Autowired
	@Qualifier("jmsTopicTemplate")
	private JmsTemplate topicjmsTemplate;

	/**
	 * 发送一条消息到指定的队列(队列模式)
	 * 
	 * @param queueName 队列名称
	 * @param message 消息内容
	 */
	public void sendQueue(String queueName, final String message) {
		queuejmsTemplate.send(queueName, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage(message);
			}
		});
	}
	
	/**
	 * 发送一条消息到指定的队列(Topic模式)
	 * 
	 * @param queueName 队列名称
	 * @param message 消息内容
	 */
	public void sendTopic(String queueName, final String message) {
		topicjmsTemplate.send(queueName, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage(message);
			}
		});
	}
	

	/**
	 * 发送一条消息到指定的队列(队列模式)
	 * 
	 * @param queueName 队列名称
	 * @param message 消息内容
	 */
	public void sendQueueMap(String queueName, final Map<String, String> message) {
		queuejmsTemplate.send(queueName, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				MapMessage mapMessage = session.createMapMessage();
				for (Map.Entry<String, String> entry : message.entrySet()) {
					mapMessage.setString(entry.getKey(), entry.getValue());
				}
				return mapMessage;
			}
		});
	}
	
	/**
	 * 发送一条消息到指定的队列(Topic模式)
	 * 
	 * @param queueName 队列名称
	 * @param message 消息内容
	 */
	public void sendTopicMap(String queueName, final Map<String, String> message) {
		topicjmsTemplate.send(queueName, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				MapMessage mapMessage = session.createMapMessage();
				for (Map.Entry<String, String> entry : message.entrySet()) {
					mapMessage.setString(entry.getKey(), entry.getValue());
				}
				return mapMessage;
			}
		});
	}
}

第三步:测试

@Test
public void demo01() throws InterruptedException{
	String xmlPath = "applicationContext.xml";
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
	MessageProducer messageProducer =  (MessageProducer) applicationContext.getBean("messageProducer");
	
	for (int i = 0; i < 3; i++) {
		messageProducer.sendQueue("my-queue", "queue:消息内容"+i);
	}
	for (int i = 0; i < 3; i++) {
		messageProducer.sendTopic("my-topic", "topic:消息内容"+i);
	}
}

结果如下:
在这里插入图片描述

9、在Spring boot中如何使用Active MQ

项目文件结构以及说明

在这里插入图片描述

第一步:搭建一个Spring Boot项目

项目完整pom.xml如下:

<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>com.study</groupId>
	<artifactId>ActiveMQ-SpringBoot</artifactId>
	<version>0.0.1-SNAPSHOT</version>


	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<java.version>1.8</java.version>
	</properties>


	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<!-- activemq 依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-activemq</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-pool</artifactId>
		</dependency>

		<!-- 热部署 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- springboot aop -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<!-- springboot-log4j -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<exclusions>
				<!-- 排除spring-boot-starter-web中自带的logback依赖 -->
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j</artifactId>
			<version>1.3.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.12</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<!-- provided:代表在编译和测试的时候用,运行,打包的时候不会打包进去 -->
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<!-- test:表示当前依赖包只参与测试时的工作:比如Junit -->
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<!-- 设定主配置类 -->
				<configuration>
					<mainClass>com.study.AppStart</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

第二步:引入activemq相关的jar包依赖

<!-- activemq 依赖 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-pool</artifactId>
</dependency>

其中activemq-pool包,若配置spring.activemq.pool.enabled=true则必须要引入,该配置的为true作用是启用连接池,所以必须要引入连接池的jar包

第三步:在application.properties文件中配置activeMQ

#配置端口和访问前缀
server.port=8080
server.servlet.context-path=/study

# activemq的账户、密码、访问地址
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.broker-url=tcp://127.0.0.1:61616

# 最大连接数
spring.activemq.pool.max-connections=10
# 是否用Pooledconnectionfactory代替普通的ConnectionFactory,设置为true,则需要引入activemq-pool
spring.activemq.pool.enabled=true
# 是否信任所有包
spring.activemq.packages.trust-all=true
# 空闲的连接过期时间,默认为30秒
spring.activemq.pool.idle-timeout=30000
# 每个连接的有效会话的最大数目。
spring.activemq.pool.maximum-active-session-per-connection=500

# 队列名配置,这个配置不要求一定是以spring.activemq开头
spring.activemq.queue-name=queue_name
spring.activemq.topic-name=topic_name

第四步:添加log4j配置文件,不然会报错


第五步:编写一个类,定义ConnectionFactory、JmsMessagingTemplate、JmsListenerContainerFactory的对象,并纳入spring容器管理

ConnectionFactory:创建连接
JmsMessagingTemplate:类似于JdbcTemplate,用户发送消息到ActiveMQ
JmsListenerContainerFactory:个人理解,从名字上来看可以理解为管理activeMQ中的每个队列监听者的容器的工厂。我们需要知道这个对象大概的作用,是用来管理消息监听者(即消费者)

package com.study.activeMQ.config;

import javax.jms.ConnectionFactory;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;

@Configuration
public class ActiveMQConfig {

	@Value("${spring.activemq.broker-url}")
	private String brokerUrl;

	@Value("${spring.activemq.user}")
	private String username;

	@Value("${spring.activemq.password}")
	private String password;


	@Bean
	public ConnectionFactory connectionFactory() {
		return new ActiveMQConnectionFactory(username, password, brokerUrl);
	}

	@Bean("jmsMessageTemplate")
	public JmsMessagingTemplate jmsMessageTemplate(ConnectionFactory connectionFactory) {
		return new JmsMessagingTemplate(connectionFactory);
	}

	// 在Queue模式中,对消息的监听需要对containerFactory进行配置
	@Bean("queueListener")
	public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory connectionFactory) {
		SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
		factory.setConnectionFactory(connectionFactory);
		factory.setPubSubDomain(false);
		return factory;
	}

	// 在Topic模式中,对消息的监听需要对containerFactory进行配置
	@Bean("topicListener")
	public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(ConnectionFactory connectionFactory) {
		SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
		factory.setConnectionFactory(connectionFactory);
		factory.setPubSubDomain(true);
		return factory;
	}
}

第六步:创建消费者

  • 创建queue模式消费者
package com.study.activeMQ.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class QueueConsumerListener
{
    private static final Logger logger = LoggerFactory.getLogger(QueueConsumerListener.class);

    //queue模式的消费者
    @JmsListener(destination="${spring.activemq.queue-name}", containerFactory="queueListener")
    public void readActiveQueue(String message) {
    	logger.info("queue接受到:" + message);
    }
}
  • 创建Topic模式消费者
    topic模式我创建了两个消费者,这两个消费者会轮询消费同一个队列的消息。
package com.study.activeMQ.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class TopicConsumerListener
{
    private static final Logger logger = LoggerFactory.getLogger(TopicConsumerListener.class);

    //topic模式的消费者
    @JmsListener(destination="${spring.activemq.topic-name}", containerFactory="topicListener")
    public void readActiveQueue1(String message) {
    	logger.info("topic1接受到:" + message);
    }
    
  //topic模式的消费者
    @JmsListener(destination="${spring.activemq.topic-name}", containerFactory="topicListener")
    public void readActiveQueue2(String message) {
    	logger.info("topic2接受到:" + message);
    }
}

第七步:消息生产者工具类

在这里我只封装了一个发送文本消息的方法

package com.study.activeMQ.producer;

import javax.jms.Destination;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

@Component
public class MessageProducer {
	
	@Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
	
	
	/**
	 * 发送消息,destination是发送到的队列,message是待发送的消息
	 * @param destination
	 * @param message
	 */
	public void sendMessage(Destination destination, final String message){
        jmsMessagingTemplate.convertAndSend(destination, message);
    }
	
}


第八步:测试

启动activeMQ。启动spring boot,调用controller实现向队列中发送消息,即可看到消息被消费的日志打印。

package com.study.controller;
import javax.jms.Destination;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.study.activeMQ.consumer.QueueConsumerListener;
import com.study.activeMQ.producer.MessageProducer;

@RestController
//@PropertySource("classpath:application-int1.properties")
public class ProducerController
{
    private static final Logger logger = LoggerFactory.getLogger(ProducerController.class);

	@Value("${spring.activemq.queue-name}")
	private String queueName;

	@Value("${spring.activemq.topic-name}")
	private String topicName;
	
	@Autowired
	private MessageProducer messageProducer;

	//http://127.0.0.1:8080/study/queue/test?msg=aaaaaaaaa
    @GetMapping("/queue/test")
    public String sendQueue(@RequestParam String msg) {
    	Destination queue = new ActiveMQQueue(queueName);
        messageProducer.sendMessage(queue, msg);
        logger.info("消息:["+msg+"]发送到"+queueName);
        return "success";
    }
    
    //http://127.0.0.1:8080/study/topic/test?msg=bbbbbbbbb
    @GetMapping("/topic/test")
    public String sendTopic(@RequestParam String msg) {
    	Destination topic = new ActiveMQTopic(topicName);
    	messageProducer.sendMessage(topic, msg);
    	logger.info("消息:["+msg+"]发送到"+topicName);
        return "success";
    }

    
}



以下是写的非常好的相关文章地址:
[1]: https://www.cnblogs.com/juepei/p/4262981.html

Active MQ C++实现通讯 Active MQ  C++实现通讯 Kagula 2011-9-13 简介 在参考资料[2]的基础上介绍如何用C++调用Active MQ的客户端API。 环境:[1]Windows XP SP3       [2]Visual Studio 2008 SP1 阅 阅读详情

相关推荐

activemq项目实例

activeMQ java资源 windows平台 点对点、发布订阅、集成spring 自己写的案例

ActiveMQ在分布式项目中的实际应用,80后程序员感慨中年危机

作为一名即将求职的程序员,面对一个可能跟近些年非常不同的 2019 年,你的就业机会和风口会出现在哪里?在这种新环境下,工作应该选择大厂还是小公司?已有几年工作经验的老兵,又应该如何保持和提升自身竞争力,转被动为主动?就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Java程序员的技术功底。最近我整理了一份复习用的面试题及面试高频的考点题及技术点梳理成一份“Java经典面试问题(含答案解析).pdf和一份网上搜集的“Java程序员面试笔试真题库.pdf。

m0_57540655的博客 361

ActiveMQ JAVA简单项目案例

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线. 本压缩包是是实现ActiveMQ中点对点与发布订阅模式的java项目,下载后可配合运行好的ActiveMQ服务直接运行。 没有ActiveMQ服务的可下载本人的ActiveMQ消息中间件,运行即可。

activemq的安装使用

最近有项目中用到消息队列,JMS规范中实现最好的开源框架就是activemq,所以选择它(当然这是我老大决定的,像我这中刚入职场的小菜鸟考虑问题还不太全面)作为消息队列传输数据,公司有有成型的消息队列框架的实现,可是公司中的框架 实现的好繁琐,考虑的好全面,考虑到了同步消息传输和异步消息传输,持久化消息存储和非持久化消息存储,消息之间点对点传输还是pubilc/subscribe(订阅)等等,考虑

panther的专栏 1422

物联网技术(AIR780E cat1-4G模块+小程序+腾讯云MQTT)驱动的智能井盖系统设计(连载01)

终端设备采用AIR780E模块作为主控器,电子模块有三轴加速度传感器、可燃气体传感器,AIR780E模块(4G模块)通过MQTT通信协议进行数据打包上传至EMQX服务器,在EMQX服务器中,用户可以自行订阅主题和发布主题,小程序通过MQTT通信协议订阅EMQX服务器的主题,服务器通过接收到硬件发布的数据,转发到微信小程序。

leida_3669的博客 2218

自偏置电流镜设计实例

自偏置电流镜设计实例 一、概述 ​ 众所周知,电流镜属于模拟电路设计中的一个基本模块,可为其他模块提供偏置电流,例如在放大器中提供偏置电流以形成尾电流源并确定直流偏置点。本文将会介绍一种自偏置的电流镜,从原理出发,并以0.18um的工艺进行设计和仿真。 二、原理 ​ 如图一所示的电路,也称之为Beta-multiply reference电路,其中M2的尺寸是M1的k倍。M3复制M4的电流,M2和M1的漏极电流相同,但是VGS并不相等。其中 VGS=2IμnCoxW/...

aonuanjiang的博客 1万+

如何在项目中运用ActiveMQ?

前言 1.这篇文章就当大家ActiveMq已经安装好了哈,不会安装的自行百度下,以下是我安装过后的界面 步骤 (一) 小编用的是SpringBoot,首先在配置文件中配置 #activemq spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.pa...

Soup's Blog 1410

PLC1200使用CB1241RS485通讯模块做从站进行Modbus Rtu通信

添加新设备(PLC)->设备和网络管理->点击PLC->看到硬件目录选择通信板->点到点->CB1241(RS485)->看到6ES7241-1CH30-1XB0选择添加,如图。指向Modbus保持寄存器数据块的指针 我这里指向了自定义的DB块数据中一个INT数组。在通信->通信处理模块->MODBUS(选择不带RTU的通信指令块)注意:接线时,TRA接485调试模块的B- TRB接调试模块的A+组态后的硬件标识符 270 对应自己组态后自动生成的。1:事务完成,且无任何错误。波特率对应自己使用的。

swmyaopeng的博客 2万+

(二)在项目中如何使用ActiveMQ的具体用法(一些常见的踩坑)?

(1)首先一般在项目中的使用无非不就是把消息发送到ActiveMQ中的消息队列中去,先要考虑是使用点对点的模式,还是使用topic发布订阅的模式来进行发送的。然后就是结合自己的业务,看你放到ActiveMQ中的是什么类型的数据,然后采用不同的Message类型 TextMessage MapMessage BytesMessage(我这里项目中采用的是字节数组类型的) StreamMessage...

王伟的博客 1582

土地利用数据从1972到2023:如何利用Landsat和Sentinel数据构建长期变化监测模型

本文详细解析了如何利用1972至2023年的Landsat和Sentinel遥感数据构建土地利用长期变化监测模型。通过多源数据融合策略、时间序列预处理流程和深度学习算法,实现高精度的土地利用分类与变化检测,为生态评估和城市规划提供科学依据。文章还探讨了验证方法和实际应用案例,展示了长期遥感数据在环境建模中的独特价值。

weixin_28720573的博客 444

【亲测好用】解决Windows系统Vscode终端无法使用yarn报错无法加载文件

我明明使用`npm i -g yarn ` 安装成功了 甚至在文件夹处 CMD 也可以看到yarn 的版本 甚至在Vscode中又重新安装了一遍yarn 为什么还是报错呢?

Aeporn的博客 888

【ActiveMQ】ActiveMQ高级特性和用法

activemq v5.8.0 release 嵌入式ActiveMQ在自己的应用程序中嵌入一个消息队列。见代码模块 no-spring包embed下。 消息存储的持久化ActiveMQ的另一个问题就是只要是软件就有可能挂掉,挂掉不可怕,怕的是挂掉之后把信息给丢了,怎么办,可以进行消息的持久化,ActiveMQ提供了几种持久化方...

猫巳的博客 3081

【开源教程25】疯壳·开源编队无人机-定高、定点、悬停

【开源教程25】疯壳·开源编队无人机-定高、定点、悬停

efans_Mike的博客 1651

Active MQ的使用

Active MQ 是Apache出品,最流行的,能力强劲的开源消息总线。 一、Active MQ特性: 1、多种语言和协议编写客户端。语言: Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP 2、完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)

hangshao的博客 4606

常用元器件使用方法13:物理层接口芯片DP83848的使用方法

介绍: DP83848是以太网物理层接口芯片,具有多种型号,从便于焊接角度考虑LQFP-48封装较为合适,采用LQFP-48封装的芯片,有2种型号,分别为DP83848I和DP83848C,如下图所示。 其主要区别是使用温度不同,如下图所示。 这2种芯片芯片网上均有销售,按理说DP83848C价格应该更加便宜,实际不然,DP83848I的价格低于DP83848C,考虑或与芯片的出货量...

snmplink的博客 1万+

Microsemi Libero系列教程(六)——Identify片上逻辑分析仪的使用

文章目录FPGA如何进行在线调试关于Microsemi片上逻辑分析仪FPGA片上逻辑分析仪原理预期效果0.准备一个创建好的Libero工程1.新建identify工程,并添加想要监测的信号2.管脚分配,编译下载3.设置触发类型4.IICE逻辑分析仪核资源占用 系列教程:Microsemi Libero系列教程 FPGA如何进行在线调试 对于嵌入式系统来说,如单片机,进行硬件级程序调试时,通常采用的是JLink/ST-Link调试器,在线调试的方式来获取程序实时运行的状态,可以观察程序运行流程、各种变量的值

whik1194的博客 1万+

关于dcim基于active Mq实现数据中心监控数据的接入

就目前我们的dcim数据中心基础设施可视化管理系统来说,目前还没有完全接入硬件,实现设备监控数据的实时数据采集。在国内的数据中心动环厂家中,很多都有现成的监控系统数据采集方案,并已经很成熟。dcim为了能够适应不同的动环监控厂家系统的接入,设计了一套监控数据转发的中间件应用,dcim Monitor App,此款软件,基于active Mq、web service、web socket、http等服务与协议,实现监控数据,从动环厂家第三方监控系统实时发送与接收。从而实现在dcim可视化场景中,实时的查看监控

huangjingqian的专栏 1504

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Active MQ入门2,Spring Boot整合Active MQ

Active MQ入门2,Spring Boot整合Active MQ 1、搭建Spring Boot项目 首先创建一个Spring Boot的项目,在pom文件中加入: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-start...

weixin_43519048的博客 1819

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JMS与Active MQ入门、Spring整合Active MQ

JMS与Active MQ入门 JMS是什么 JMS(Java Messaging Service)是Java平台上有关面向消息中间件的技术规范,实际上是一套api,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,ActiveMQ而是这个规范的一个具体实现。JMS是一种与厂商无关的 API,用来访问收发系统消息,它类似于JDBC. ...

weixin_43519048的博客 1894

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Active MQ 使用

MQ使用教程

chenfengstrong的专栏 676

Active MQ使用

Active MQ使用 Kagula 2011-9-6 介绍   Active MQ是个消息队列管理器,用于通讯的中间件。 Java + Active MQ的常见使用方式有两种:[1]点对点方式(Producer/Consumer)[2]发布/订阅者方式(Publisher/Subscriber Model)   测试环境[1]JDK1.6.x [2]Eclipse Indigo [3

lee353086的专栏 1万+

Active MQ的持久化

MQ的高可用: 1、事务 2、持久 3、签收 前3个都是MQ本身的特性,如果MQ出现了故障,上面的3个就无法保证了 4、可持久化 只有第4个可持久化才能保证高可用,通常来说,执行持久化的机器要和安装MQ的机器分开,才能保证不会产生事故 V5.3用的是Kaha DB V5.9用的是Apache ZooKeeper ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB 就是发送者将消息发送出去以后,消息中心首先将消息存储到本地数据文件,内存数据库或者远程数据库,再试图将消息发送给接收

qxf1374268的博客 482

Spring中Active MQ的基本使用

目录 1. JMS(JAVA消息服务) 2.Active MQ 3.参考链接 1. JMS(JAVA消息服务) 1.1.JMS(JAVA Message Service,java消息服务)API是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。它使分布式通信耦合度更低,消息服务更加可靠以及异步性。 1.2.消息模型:点对点和发布订...

遥远 456

active mq与Spring的整合

【前言】Java消息服务(JMS)广泛应用在跨系统的异步通信中,优势在于减少响应时间和降低耦合,通常我们会把比较耗时且不需要立即返回结果的操作放入消息队列中。 【分类】1.点对点消息模型 :每个消息只有一个接受者,消息发送和消息接收者之间无直接关联。当消息发送者发送消息时,无论接收者在不在运行,都能获取到消息,并在收到时发送确认消息。 2.发布订阅模型:一个消息可以有多个订阅者,发布、订阅之间

虐汪狂人巴甫洛夫的博客 1461

active mq topic消费后删除_一文读懂MQ消息队列

MQ(消息队列)在软件架构中是经常被使用的,特别是在分布式系统中也是使用频率很高的组件。以下从消息队列的使用场景、概念、常见问题及解决方案来详细讲解。一、消息队列使用场景1.1 常见的使用场景系统解耦在分布式环境下,系统间的相互依赖,最终会会导致整个依赖关系混乱,特别在微服务环境下,会出现相互依赖,甚至是循环依赖的情况,对后期系统的拆分和优化都带来极大负担。那么我们就可以用MQ来进行处理。上游系统...

weixin_39718006的博客 1216

Rabbit MQ

Rabbit MQ是一款开源的,Erlang语言编写的,基于AMQP高级队列协议的消息中间件。可以用它来解耦、异步、削峰。解耦:并行任务串行化处理异步:不需要等待消息的接收者的响应削峰:把一些并发量非常高的或负载非常大的方法做一个负载均衡缺点:1、降低了系统的稳定性。本来系统运行的好好的,现在你非要加一个消息队列进去,那消息队列挂了的话,那系统也会受影响。2、增加了系统的复杂性。加入消息队列进去,要考虑很多方面的问题。比如:一致性的问题,如何保证消息不被重复消费,如果保证消息可靠性传输。

weixin_46734140的博客 877
上一篇: 概率抽奖常用两种方式
下一篇: java中ThreadLocal对象理解和使用
村口老师傅
博客等级 码龄9年 67粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值