本文来自于csdn,文章通过介绍ActiveMQ的安装,使用,搭建等等,简单整理了ActiveMQ。

本文转自:http://www.uml.org.cn/zjjs/201802111.asp

一.背景介绍

1.1 java消息服务:

不同系统之间的信息交换,是我们开发中比较常见的场景,比如系统A要把数据发送给系统B,这个问题我们应该如何去处理? 1999年,原来的SUN公司领衔提出了一种面向消息的中间件服务--JMS规范(标准);常用的几种信息交互技术(httpClient、hessian、dubbo、jms、webservice 五种).

1.2 JMS概述:

JMS即Java消息服务(Java Message Service的简称),是Java EE 的标准/规范之一。这种规范(标准)指出:消息的发送应该是异步的、非阻塞的。也就是说消息的发送者发送完消息后就直接返回了,不需要等待接收者返回后才能返回,发送者和接收者可以说是互不影响。所以这种规范(标准)能够减轻或消除系统瓶颈,实现系统之间去除耦合,提高系统的整体可伸缩性和灵活性。JMS只是Java EE中定义的一组标准API,它自身并不是一个消息服务系统,它是消息传送服务的一个抽象,也就是说它定义了消息传送的接口而并没有具体实现。

1.3 ActiveMQ概述:

我们知道JMS只是消息服务的一组规范和接口,并没有具体的实现,而ActiveMQ就是JMS规范的具体实现;它是Apache下的一个项目,采用Java语言开发;是一款非常流行的开源消息服务器.

1.4 ActiveMQ与JMS关系:

我们知道,JMS只是定义了一组有关消息传送的规范和标准,并没有真正实现,也就说JMS只是定义了一组接口而已;就像JDBC抽象了关系数据库访问、JPA抽象了对象与关系数据库映射、JNDI抽象了命名目录服务访问一样,JMS具体的实现由不同的消息中间件厂商提供,比如Apache ActiveMQ就是JMS规范的具体实现,Apache ActiveMQ才是一个消息服务系统,而JMS不是。

二.ActiveMQ的使用

2.1 ActiveMQ环境搭建:

1.ActiveMQ运行需要Java的支持,首先需要配置Java环境变量;

3.切换到解压后的activemq的bin目录下 cd / usr / local / apache - activemq - 5.15.2 去启动

3.切换到bin目录下,启动:./activemq start ;关闭: . / activemq stop

4.启动后有两个端口号,一个是web控制台:8161,一个是消息服务broker连接端口:61616

5.web管理控制台admin URL地址:http : // localhost : 8161 默认登录账号 admin 密码 admin,注意:Linux防火前要关闭 ;通过这个地址可以即时访问交互信息.如下图:

消息服务broker URL地址 : tcp : // localhost : 61616

2.2 Java消息队列JMS整体设计结构

2.2.1 基本要素:1、生产者producer ; 2、消费者consumer ; 3、消息服务broker

2.2.1 交互模型:

2.2.3 JMS两种消息传送模式

点对点( Point-to-Point):专门用于使用队列Queue传送消息;基于队列Queue的点对点消息只能被一个消费者消费,如多个消费者都注册到同一个消息队列上,当生产者发送一条消息后,而只有其中一个消费者会接收到该消息,而不是所有消费者都能接收到该消息。

发布/订阅(Publish/Subscribe):专门用于使用主题Topic传送消息。基于主题的发布与订阅消息能被多个消费者消费,生产者发送的消息,所有订阅了该topic的消费者都能接收到。

2.3 Java消息队列JMS API总体概览:

2.3.1JMS API 概览

JMS API可以分为3个主要部分:

1、公共API:可用于向一个队列或主题发送消息或从其中接收消息;

2、点对点API:专门用于使用队列Queue传送消息;

3、发布/订阅API:专门用于使用主题Topic传送消息。

JMS公共API:

在JMS公共API内部,和发送与接收消息有关的JMS API接口主要是:ConnectionFactory / Connection / Session / Message / Destination / MessageProducer / MessageConsumer . 它们的关系是:一旦有了ConnectionFactory,就可以创建Connection,一旦有了Connection,就可以创建Session,而一旦有了Session,就可以创建 Message 、MessageProducer 和 MessageConsumer 。

JMS点对点API:

点对点(p2p)消息传送模型API是指JMS API之内基于队列(Queue)的接口:QueueConnectionFactory / QueueConnection / QueueSession / Message / Queue / QueueSender / QueueReceiver .

从接口的命名可以看出,大多数接口名称仅仅是在公共API接口

名称之前添加Queue一词。一般来说,使用点对点消息传送模型的应用程序将使用基于队列的API,而不使用公共API 。

JMS发布/订阅API:

发布/订阅消息传送模型API是指JMS

API之内基于主题(Topic)的接口:TopicConnectionFactory / TopicConnection /

TopicSession / Message / Topic / TopicPublisher / TopicSubscriber . 由于基于主题(Topic)的JMS API类似于基于队列(Queue)

的API,因此在大多数情况下,Queue这个词会由Topic取代。

2.4 ActiveMQ点对点发送与接收消息示例

2.4.1 简单示例:

写一个采用Queue队列方式点对点发送接收文本信息的Demo,先写发送者,如下:

package com.kinglong.activemq.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/** 
* 消息发送者 

*/ 
public class Sender {

/**消息服务器的连接地址**/ 
public static final String BROKER_URL = "tcp://192.168.174.129:61616";

public static void main(String[] args) { 
Sender sender = new Sender(); 
sender.sendMessage("Hello ActiveMQ."); 
}

/** 
* 发送消息 

* @param msg 
*/ 
public void sendMessage (String msg) {

Connection connection = null; 
Session session = null; 
MessageProducer messageProducer = null;

try { 
//1.创建一个连接工厂 
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

//2.创建一个连接 
connection = connectionFactory.createConnection();

//3.创建一个Session 
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

//4.创建消息,此处创建了一个文本消息 
Message message = session.createTextMessage(msg);

//5.创建一个目的地 
Destination destination = session.createQueue("myQueue");

//6.创建一个消息的生产者(发送者) 
messageProducer = session.createProducer(destination);

//7.发送消息 
messageProducer.send(message);

} catch (JMSException e) { 
e.printStackTrace(); 
} finally { 
try { 
//关闭连接释放资源 
if (null != messageProducer) { 
messageProducer.close(); 

if (null != session) { 
session.close(); 

if (null != connection) { 
connection.close(); 

} catch (JMSException e) { 
e.printStackTrace(); 



}

再写接收者:

package com.kinglong.activemq.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class Receiver {

/**消息服务器的连接地址**/ 
public static final String BROKER_URL = "tcp://192.168.174.129:61616";

public static void main(String[] args) { 
Receiver receiver = new Receiver(); 
receiver.receiveMessage(); 
}

/** 
* 接收消息 

*/ 
public void receiveMessage () {

Connection connection = null; 
Session session = null; 
MessageConsumer messageConsumer = null;

try { 
//1.创建一个连接工厂 
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

//2.创建一个连接 
connection = connectionFactory.createConnection();

//3.创建一个Session 
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

//4.创建一个目的地 
Destination destination = session.createQueue("myQueue");

//5.创建一个消息的消费者(接收者) 
messageConsumer = session.createConsumer(destination);

//接收消息之前,需要把连接启动一下 
connection.start();

//6.接收消息 
Message message = messageConsumer.receive();

//判断消息的类型 
if (message instanceof TextMessage) { //判断是否是文本消息 
String text = ((TextMessage) message).getText(); 
System.out.println("接收到的消息内容是:" + text); 

} catch (JMSException e) { 
e.printStackTrace(); 
} finally { 
try { 
//关闭连接释放资源 
if (null != messageConsumer) { 
messageConsumer.close(); 

if (null != session) { 
session.close(); 

if (null != connection) { 
connection.close(); 

} catch (JMSException e) { 
e.printStackTrace(); 



}

总结:

创建过程中有几个重要的注意点,说明一下:

1. session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); 
// 其中:Boolean.FALSE表示本次会话不开启事务管理,假如需要开启事务管理,将其改为Boolean.TRUE即可 
//同时需要在发送消息后添加session.commit(),否则,消息是不会被提交的. 
//Session.AUTO_ACKNOWLEDGE表示消息确认机制 
AUTO_ACKNOWLEDGE:自动确认 
CLIENT_ACKNOWLEDGE:客户端确认 
SESSION_TRANSACTED:事务确认,如果使用事务推荐使用该确认机制 
AUTO_ACKNOWLEDGE:懒散式确认,消息偶尔不会被确认,也就是消息可能会被重复发送.但发生的概率很小 
2. connection.start(); 
//在消息接收端,接受消息前需要加入这段代码,开启连接,否则一样无法获取消息. 
3. Destination destination = session.createQueue("myQueue"); 
//创建目的地时,如果做测试收不到信息,可以将目的地名称修改一下,我用的是IDEA,不清楚为何, 
//有时候收不到信息,修改一下就好了,猜测可能是缓存的原因吧

发布与订阅的topic方式实际与点对点的queue方式,代码通用很多,只是在创建目的地Destination时候创建为

Destination destination = session.createTopic("myTopic

2.4.2Queue与Topic比较

2.4.3拉模式与推模式

a.点对点消息,如果没有消费者在监听队列,消息将保留在队列中,直至消息消费者连接到队列为止。这种消息传递模型是

传统意义上的懒模型或轮询模型。在此模型中,消息不是自动推动给消息消费者的,而是要由消息消费者从队列中请求获得(拉模式)。

b.pub/sub消息传递模型基本上是一个推模型。在该模型中,消息会自动广播,消息消费者无须通过主动请求或轮询主题的方法来获得新的消息。

2.5 ActiveMQ消息类型

1、TextMessage 文本消息:携带一个java.lang.String作为有效数据(负载)的消息,可用于字符串类型的信息交换;

2、ObjectMessage 对象消息:携带一个可以序列化的Java对象作为有效负载的消息,可用于Java对象类型的信息交换;

3、MapMessage 映射消息:携带一组键值对的数据作为有效负载的消息,有效数据值必须是Java原始数据类型(或者它们的包装类)及String。即:byte , short , int , long , float , double , char , boolean , String

4、BytesMessage 字节消息 :携带一组原始数据类型的字节流作为有效负载的消息;

5、StreamMessage 流消息:携带一个原始数据类型流作为有效负载的消息,它保持了写入流时的数据类型,写入什么类型,

则读取也需要是相同的类型;

需要注意的是:如果使用对象消息做Demo时,如果使用之前的连接创建方式可能会无法接收到消息,因为安全问题.所以,如果想要使用Demo测试对象消息,创建连接时建议改为这样(官网推荐的连接方式):

//创建对象消息连接工厂 
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(BROKER_URL); 
List<String > list = new ArrayList<String>(); 
list.add("com.kinglong.activemq.receiver"); 
list.add("com.kinglong.activemq.model"); 
activeMQConnectionFactory.setTrustedPackages(list);

2.6 ActiveMQ事务消息和非事务消息

消息分为事务消息和非事务消息

1、事务消息:创建会话Session使用transacted=true

connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

2、非事务消息:创建会话Session使用transacted=false

connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

事务消息必须在发送和接收完消息后显式地调用session.commit();

事务性消息,不管设置何种消息确认模式,都会自动被确认;与设置的确认机制无关,但官方推荐事务性消息使用事务确认机制.

2.7 ActiveMQ消息确认机制

消息只有在被确认之后,才认为已经被成功消费,然后消息才会从队列或主题中删除。消息的成功消费通常包含三个阶段:

(1)、客户接收消息;(2)、客户处理消息;(3)、消息被确认;

确认机制前面提过一下,共有四种:

(1)、Session.AUTO_ACKNOWLEDGE;客户(消费者)成功从receive方法返回时,或者从MessageListener.onMessage方法成功返回时,会话自动确认消息,然后自动删除消息.

(2)、Session.CLIENT_ACKNOWLEDGE;客户通过显式调用消息的acknowledge方法确认消息,。 即在接收端调用message.acknowledge();方法,否则,消息是不会被删除的.

(3)、Session. DUPS_OK_ACKNOWLEDGE ;不是必须确认,是一种“懒散的”消息确认,消息可能会重复发送,在第二次重新传送消息时,消息头的JMSRedelivered会被置为true标识当前消息已经传送过一次,客户端需要进行消息的重复处理控制。

(4)、 Session.SESSION_TRANSACTED;事务提交并确认。

2.8 ActiveMQ持久化消息与非持久化消息

messageProducer.setDeliveryMode(DeliveryMode. NON_PERSISTENT);//不持久化
messageProducer.setDeliveryMode(DeliveryMode.

PERSISTENT);//持久化的,当然activemq发送消息默认都是持久化的

说明:

设置完后,如果为持久化,那么消息在没有被消费前都会被写入本地磁盘kahadb文件中保存起来,即使服务器宕机,也不会影响

消息.如果是非持久化的,那么,服务一旦宕机之类的情况发生,消息即会被删除.

ActiveMQ默认是持久化的.

2.9 ActiveMQ消息过滤

ActiveMQ提供了一种机制,可根据消息选择器中的标准来执行消息过滤,只接收符合过滤标准的消息;

生产者可在消息中放入特有的标志,而消费者使用基于这些特定的标志来接收消息;

1、发送消息放入特殊标志:message . setString Property ( name , value ) ;

2、接收消息使用基于特殊标志的消息选择器:

MessageConsumer createConsumer(Destination destination, String messageSelector);

注:消息选择器是一个字符串,语法与数据库的SQL相似,相当于SQL语句where条件后面的内容;

具体代码如下:

发送端代码:

package com.bjpowernode.activemq.selector;

import org.apache.activemq.Active

MQConnectionFactory;

import javax.jms.*;

/** 
* 消息发送者 

*/ 
public class Sender {

/**消息服务器的连接地址**/ 
public static final String BROKER_URL = "tcp://192.168.174.129:61616";

public static void main(String[] args) { 
Sender sender = new Sender(); 
sender.sendMessage("Hello ActiveMQ."); 
}

/** 
* 发送消息 

* @param msg 
*/ 
public void sendMessage (String msg) {

Connection connection = null; 
Session session = null; 
MessageProducer messageProducer = null;

try { 
//1.创建一个连接工厂 
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

//2.创建一个连接 
connection = connectionFactory.

createConnection();

//3.创建一个Session 
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

//5.创建一个目的地 
Destination destination = session.create

Queue("myQueue");

//6.创建一个消息的生产者(发送者) 
messageProducer = session.createProducer

(destination);

//设置发送的消息是否需要持久化 
messageProducer.setDeliveryMode(Delivery

Mode.NON_PERSISTENT);//这里使用不持久化

//创建一个循环,测试消息标识的使用 
for (int i=0; i<20; i++) { 
//4.创建消息,此处创建了一个文本消息 
Message message = session.createText

Message(msg+i);

//将消息设置一个特有的标识 
message.setIntProperty("id", i);

//7.发送消息 
messageProducer.send(message); 

} catch (JMSException e) { 
e.printStackTrace(); 
} finally { 
try { 
//关闭连接释放资源 
if (null != messageProducer) { 
messageProducer.close(); 

if (null != session) { 
session.close(); 

if (null != connection) { 
connection.close(); 

} catch (JMSException e) { 
e.printStackTrace(); 



}

接收端代码:

package com.bjpowernode.activemq.selector;

import org.apache.activemq.ActiveMQ

ConnectionFactory;

import javax.jms.*;

public class Receiver {

/**消息服务器的连接地址**/ 
public static final String BROKER_URL = "tcp://192.168.174.129:61616";

public static void main(String[] args) { 
Receiver receiver = new Receiver(); 
receiver.receiveMessage(); 
}

/** 
* 接收消息 

*/ 
public void receiveMessage () {

Connection connection = null; 
Session session = null; 
MessageConsumer messageConsumer = null;

try { 
//1.创建一个连接工厂 
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

//2.创建一个连接 
connection = connectionFactory.

createConnection();

//3.创建一个Session 
session = connection.createSession

(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

//4.创建一个目的地 
Destination destination = session.createQueue("myQueue");

//5.创建一个消息的消费者(接收者),

selector即为消息选择器,通过选择需要的标识,过滤消息接受id为10-15之 //间的消息 
String selector = "id >=10 and id<=15"; 
messageConsumer = session.createConsumer

(destination, selector);

//接收消息之前,需要把连接启动一下 
connection.start();

while (true) { 
//6.接收消息 同步接收 
Message message = messageConsumer.

receive();

//判断消息的类型 
if (message instanceof TextMessage)

{ //判断是否是文本消息 
String text = ((TextMessage) message).getText(); 
System.out.println("接收到的消息内容是:" + text); 


} catch (JMSException e) { 
e.printStackTrace(); 
} finally { 
try { 
//关闭连接释放资源 
if (null != messageConsumer) { 
messageConsumer.close(); 

if (null != session) { 
session.close(); 

if (null != connection) { 
connection.close(); 

} catch (JMSException e) { 
e.printStackTrace(); 



}

2.10 ActiveMQ消息接收方式

同步接收:receive()方法接收消息叫同步接收,就是之前的Demo代码使用的接收方式.在不使用循环方法时接收端代码执行

一次即结束.

异步接收:使用监听器接收消息,这种接收方式叫异步接收,接收端会一直处于监听状态,只要有消息产生,即会接收消息.

下面是异步接收代码:

package com.bjpowernode.activemq.listener;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class Receiver {

/**消息服务器的连接地址**/ 
public static final String BROKER_URL = "tcp://192.168.174.129:61616";

public static void main(String[] args) { 
Receiver receiver = new Receiver(); 
receiver.receiveMessage(); 
}

/** 
* 接收消息 

*/ 
public void receiveMessage () {

Connection connection = null; 
Session session = null; 
MessageConsumer messageConsumer = null;

try { 
//1.创建一个连接工厂 
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

//2.创建一个连接 
connection = connectionFactory.createConnection();

//3.创建一个Session 
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

//4.创建一个目的地 
Destination destination = session.createQueue("myQueue");

//5.创建一个消息的消费者(接收者) 
messageConsumer = session.createConsumer(destination);

//接收消息之前,需要把连接启动一下 
connection.start();

//6.接收消息 同步接收 
//Message message = messageConsumer.receive();

//异步接收,使用监听器接收消息 
messageConsumer.setMessageListener(new MessageListener(){ 
public void onMessage(Message message) { 
//判断消息的类型 
if (message instanceof TextMessage) { //判断是否是文本消息 
String text = null; 
try { 
text = ((TextMessage) message).getText(); 
} catch (JMSException e) { 
e.printStackTrace(); 

System.out.println("接收到的消息内容是:" + text); 


}); 
} catch (JMSException e) { 
e.printStackTrace(); 
} finally { 
/*try { 
//关闭连接释放资源 
if (null != messageConsumer) { 
messageConsumer.close(); 

if (null != session) { 
session.close(); 

if (null != connection) { 
connection.close(); 

} catch (JMSException e) { 
e.printStackTrace(); 
}*/ 


}

三.ActiveMQ的集成使用:

3.1ActiveMQ与Spring集成(以下是一个简单的上手Demo):

鉴于发送端与接收端pom文件依赖相同,所以只写一份,依赖如下:

[html] view plain copy
<!--spring-jms依赖--> 
<dependency> 
<groupId>org.springframework</groupId> 
<artifactId>spring-jms</artifactId> 
<version>4.3.13.RELEASE</version> 
</dependency>

<!--activemq的jar依赖--> 
<dependency> 
<groupId>org.apache.activemq</groupId> 
<artifactId>activemq-client</artifactId> 
<version>5.15.2</version> 
</dependency>

<!-- JMS规范的jar依赖 --> 
<dependency> 
<groupId>javax.jms</groupId> 
<artifactId>javax.jms-api</artifactId> 
<version>2.0.1</version> 
</dependency>

发送端:(需要两个配置文件)

1. applicationContext.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" 
xsi:schemaLocation="http://www.springframework.

org/schema/beans http://www.springframework.

org/schema/beans

/spring-beans.xsd">

<import resource="applicationContext-jms.xml"/>

</beans>

2. applicationContext-jms.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" 
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.xsd">

<context:component-scan base-package="com.kinglong.activemq.sender"/>

<!-- 配置一个连接工厂 --> 
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnection

Factory"> 
<property name="brokerURL" value="tcp://192.168.

174.129:61616"/> 
</bean>

<!-- 配置JmsTemplate --> 
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> 
<property name="connectionFactory" ref="connection

Factory" /> 
<property name="defaultDestinationName"

value="springTopic" /> 
<!--指定消息传送模式,true表示发布订阅、

false表示点对点--> 
<property name="pubSubDomain" value="true"/> 
</bean>

</beans>

发送类:

package com.kinglong.activemq.sender;

import org.springframework.beans.factory.annotation

.Autowired; 
import org.springframework.jms.core.

JmsTemplate; 
import org.springframework.jms.core.

MessageCreator; 
import org.springframework.stereotype.Component;

import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.Session; 
@Component 
public class Sender {

@Autowired 
private JmsTemplate jmsTemplate;

public void sendMessage (final String msg) { 
//发送消息 
jmsTemplate.send(new MessageCreator() { 
public Message createMessage(Session

session) throws JMSException { 
return session.createTextMessage(msg); 

}); 
}

}

下面是测试类:

package com.kinglong.activemq.sender;

import org.springframework.context.support.

ClassPathXmlApplicationContext;

public class Test { 
public static void main(String[] args) {

ClassPathXmlApplicationContext context = 
new ClassPathXmlApplicationContext("classpath:app

licationContext.xml");

Sender springSender = (Sender)context.getBean("sender");

springSender.sendMessage("Spring jms ActiveMQ.");


}

接收端(也同样需要两个配置文件,这里使用异步接收,所以需要配置一个监听器):

1. applicationContext.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" 
xsi:schemaLocation="http://www.springframework.

org/schema/beans http://www.springframework.

org/schema

/beans/spring-beans.xsd">

<import resource="applicationContext-jms.xml"/>

</beans>

2. applicationContext-jms.xml

监听器:(MyMessageListener)

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org

/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XML

Schema-instance" 
xmlns:context="http://www.springframework.

org/schema/context" 
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.xsd">

<context:component-scan base-package="com

.kinglong.activemq.receiver"/>

<!-- 配置一个连接工厂 --> 
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> 
<property name="brokerURL" value="tcp://192.

168.174.129:61616"/> 
</bean>

<!-- 配置JmsTemplate --> 
<bean id="jmsTemplate" class="org.springframework.

jms.core.JmsTemplate"> 
<property name="connectionFactory" ref="

connectionFactory" /> 
<property name="defaultDestinationName"

value="springTopic" /> 
<!--指定消息传送模式,true表示发布订阅、

false表示点对点--> 
<property name="pubSubDomain" value="true"/> 
</bean>

<!-- 我们自定义的一个消息监听器 --> 
<bean id="receiverListener" class="com.kinglong.activemq.receiver.MyMessage

Listener" />

<!-- 配置一个sping监听器的容器 --> 
<bean class="org.springframework.jms.listener.Default

MessageListenerContainer"> 
<property name="connectionFactory" ref="

connectionFactory"/> 
<property name="destinationName" value="

springTopic"/> 
<property name="messageListener" ref="receiver

Listener" /> 
<!--指定消息传送模式,true表示发布订阅、

false表示点对点--> 
<property name="pubSubDomain" value="true"/> 
</bean>

</beans>

下面是测试类:

package com.kinglong.activemq.receiver;

import org.springframework.context.support.Class

PathXmlApplicationContext;

public class Test {

public static void main(String[] args) {

ClassPathXmlApplicationContext context = 
new ClassPathXmlApplicationContext("classpath:

applicationContext.xml");

}

}

说明:由于使用的是Topic发布订阅模式,所以测试时一定先开启接收端服务,再开启发送端发送消息,否则接不到消息.

相比较之下,spring集成的activemq使用已经相当简化,与原始版相比,整个链接对象的创建全部交给spring完成了,所以效率上更高了.

其次,各属性配置也都从代码中剥离归整在配置文件里,使得修改配置也变得更为容易,但是,个人觉得还是有必要学习学习原始版本,

可以更好地理解其创建过程,加深理解.

3.2ActiveMQ与Springboot集成(以下是一个简单的上手Demo):

同样pom依赖,因为依赖相同,所以只写一份,如下:

<!--配置父级依赖--> 
<parent> 
<groupId>org.springframework.boot</groupId> 
<artifactId>spring-boot-starter-parent</artifactId> 
<version>1.5.9.RELEASE</version> 
<relativePath/> <!-- lookup parent from repository --> 
</parent>

<!--属性配置--> 
<properties> 
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
<java.version>1.8</java.version> 
</properties>

<dependencies>

<!--开发springboot的Java程序的起步依赖--> 
<dependency> 
<groupId>org.springframework.boot</groupId> 
<artifactId>spring-boot-starter</artifactId> 
</dependency>

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

<!--springboot集成activemq的起步依赖--> 
<dependency> 
<groupId>org.springframework.boot</groupId> 
<artifactId>spring-boot-starter-activemq</artifactId> 
</dependency>

</dependencies>

发送端:

只有一个主配置文件:application.properties

spring.activemq.broker-url=tcp://192.168.174.129:61616

#发布订阅模式 
spring.jms.pub-sub-domain=true

main方法类:

package com.kinglong.activemq;

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.

SpringBootApplication; 
import org.springframework.context.Configurable

ApplicationContext;

@SpringBootApplication 
public class SenderApplication {

public static void main(String[] args) {

ConfigurableApplicationContext context = SpringApplication.run(SenderApplication.

class, args);

SpringBootSender springBootSender = (SpringBootSender)context.getBean

("springBootSender");

springBootSender.sendMessage("springboot

activemq."); 
}

}

发送者:SpringBootSender

package com.kinglong.activemq;

import org.springframework.beans.factory.

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

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

@Component 
public class SpringBootSender {

@Autowired //注入JmsTemplate 
private JmsTemplate jmsTemplate;

//发送消息,"myTopic"是发送到的队列

destination,message是待发送的消息 
public void sendMessage(String message) { 
jmsTemplate.send("myTopic", new Message

Creator() { 
@Override 
public Message createMessage(Session session)

throws JMSException { 
return session.createTextMessage(message); 

}); 

}

接收端:

主配置文件与发送端相同

main方法类:ReceiverApplication

package com.kinglong.activemq;

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.

SpringBootApplication; 
import org.springframework.context.Configurable

ApplicationContext;

import javax.jms.JMSException;

@SpringBootApplication 
public class ReceiverApplication {

public static void main(String[] args) throws

JMSException {

ConfigurableApplicationContext context = SpringApplication.run(ReceiverApplication.

class, args);

//这里采用异步接收


}

监听器:MessageListenerReceiver

package com.kinglong.activemq;

import org.springframework.jms.annotation.JmsListener; 
import org.springframework.stereotype.Component;

@Component 
public class MessageListenerReceiver {

@JmsListener(destination = "myTopic") 
public void receiveQueue(String text) { 
System.out.println("Consumer收到的报文为:" + text); 

}

OVER! 是不是发现springboot集成的ActiveMQ更加精巧了?配置文件都不用写了,springboot全帮我们做完了.不过,还是那句话,建议把原始版本原理,思路整通了再做spring或是springboot的集成,要不感觉直接理解起来springboot的发送和接收还是比较抽象的.

四.ActiveMQ集群

4.1 何为集群?

集群就是将相同的程序、功能,部署在两台或多台服务器上,这些服务器对外提供的功能是完全一样的。通过不断横向扩展增加服务器的方式,以提高服务的能力。

4.1.1 不集群模式

4.1.2 集群模式

4.2 集群的优势:

1、集群可以解决单点故障问题;

2、集群可以提高系统服务能力;

ActiveMQ---知识点整理的更多相关文章

  1. ACM个人零散知识点整理

    ACM个人零散知识点整理 杂项: 1.输入输出外挂 //读入优化 int 整数 inline int read(){ int x=0,f=1; char ch=getchar(); while(ch& ...

  2. Android 零散知识点整理

    Android 零散知识点整理 为什么Android的更新试图操作必须在主线程中进行? 这是因为Android系统中的视图组件并不是线程安全的.通常应该让主线程负责创建.显示和更新UI,启动子线程,停 ...

  3. vue前端面试题知识点整理

    vue前端面试题知识点整理 1. 说一下Vue的双向绑定数据的原理 vue 实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫 ...

  4. kafka知识点整理总结

    kafka知识点整理总结 只不过是敷衍 2017-11-22 21:39:59 kafka知识点整理总结,以备不时之需. 为什么要使用消息系统: 解耦 并行 异步通信:想向队列中放入多少消息就放多少, ...

  5. JSP页面开发知识点整理

    刚学JSP页面开发,把知识点整理一下. ----------------------------------------------------------------------- JSP语法htt ...

  6. JS知识点整理(二)

    前言 这是对平时的一些读书笔记和理解进行整理的第二部分,第一部分请前往:JS知识点整理(一).本文包含一些易混淆.遗漏的知识点,也会配上一些例子,也许不是很完整,也许还会有点杂,但也许会有你需要的,后 ...

  7. css入门知识点整理

    css入门知识点整理 不要嘲笑我这个蒟蒻..例子来源:w3school css其实就分为两个东西,一个是选择器,另外一个是声明.声明定义了某个对象的属性的值,这都是html的内容.重点要关注的是选择器 ...

  8. activity生命周期知识点整理

    activity生命周期知识点整理 Activity: 是一个应用组件,用户可与其提供的屏幕进行交互.窗口通常会充满屏幕,但也可以小于屏幕并浮动在其他窗口之上. 一个activity的什么周期: 启动 ...

  9. 【Android 面试基础知识点整理】

    针对Android面试中常见的一些知识点整理,Max 仅仅是个搬运工.感谢本文中引用文章的各位作者,给大家分享了这么多优秀文章.对于当中的解析,是原作者个人见解,有错误和不准确的地方,也请大家积极指正 ...

  10. 2019.10.15 CSP初赛知识点整理

    初赛需要的知识点整理如下: (1)计算机的硬件组成与基本常识 (2)单位/进制的转换 (3)进制/逻辑运算相关 (4)概率与期望 (5)排序的各种性质 (6)简单数据结构的使用(栈.队列.链表等) ( ...

随机推荐

  1. phpStorm 显示行号

  2. 170523、快速提升你 MySQL 数据库的段位

    MySQL 数据库知识脉络,大致可以分为四大模块: ● MySQL 体系结构: ● MySQL 备份恢复: ● MySQL 高可用集群: ● MySQL 优化. 从四大模块中,抽离7个部分给大家做分析 ...

  3. CMDB经验分享之 – 剖析CMDB的设计过程

    作为IT管理的核心,CMDB逐渐成为系统管理项目实施的热点.在很多的案例中,由于忽视了CMDB的因素,ITIL的深入应用受到了极大的挑战.同时,由于CMDB是IT管理信息的集中,CMDB也是一个重要的 ...

  4. python中的Redis键空间通知(过期回调)

    介绍 Redis是一个内存数据结构存储库,用于缓存,高速数据摄取,处理消息队列,分布式锁定等等. 使用Redis优于其他内存存储的优点是Redis提供持久性和数据结构,如列表,集合,有序集和散列. 在 ...

  5. cocos2d动作

    1.动作的基类是CCAction,通过继承它可以实现很多不同的动作,主要分为三大类: (1)CCFiniteTimeAction(有限次动作执行类) (2)CCSpeed(节点执行速度类) (3)CC ...

  6. mysql 数据操作 单表查询 where 约束 目录

    mysql 数据操作 单表查询 where约束 between and or mysql 数据操作 单表查询 where约束 is null in mysql 数据操作 单表查询 where约束 li ...

  7. python高级之Flask框架

    目录: Flask基本使用 Flask配置文件 Flask路由系统 Flask模版 Flask请求与响应 Flask之Session Flask之蓝图 Flask之message 中间件 Flask插 ...

  8. [py][mx]实现按照课程机构排名,按照学习人数排名

    原型是 实现效果 因为要按照这两个指标排名, 模型中现在还没有这2个字段(整数),所以需要修改模型. 修改模型,添加2个排序指标的字段 class CourseOrg(models.Model): . ...

  9. #C++初学记录(素数判断)

    练习题目二 素数判断 A prime number is a natural number which has exactly two distinct natural number divisors ...

  10. 53. Maximum Subarray(动态规划 求最大子数组)

      Find the contiguous subarray within an array (containing at least one number) which has the larges ...