ActiveMQ
基础概念
JMS和AMQP
**JMS:**Java平台消息中间件 【消息生产者、queue队列、消息消费者】
AMQP:跨平台,【消息生产者、exchange交换机、queue队列、消息消费者】
JMS模型
- 点对点模型
- 发布、订阅模型
安装activemq
基本命令
#解压
tar -zxf apache-activemq-5.9.0-bin.tar.gz
#检查权限,如果权限不足,需要修改文件权限
ls -al apache-activemq-5.9.0/bin
chmod 755 activemq
#复制应用到本地目录
cp -r apache-activemq-5.9.0 /usr/local/activemq
#启动命令
/usr/local/activemq/bin/activemq start
#检查进程
ps aux | grep activemq
#访问
http://ip:8161/admin username:admin pwd:admin
#修改端口
cd /usr/local/activemq/conf/jetty.xml
关键字:jettyPort
#修改密码
vi /usr/local/activemq/conf/users.properties
内容 username:pwd
#重启
/usr/local/activemq/bin/activemq restart
#关闭
/usr/local/activemq/bin/activemq stop
#修改提供服务端口
activemq.xml 默认61616
术语
- destination目的地
- producer消息生成者
- consumer|receiver消息消费者
- message消息
Java中使用
基本使用
导入包:
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
点对点模型
producer
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
public class HelloWorldProducer {
/**
* 生产消息
*/
public void sendHelloWorldActiveMQ(/*String msgTest*/ Users msgTest){
//定义链接工厂
ConnectionFactory connectionFactory = null;
//定义链接对象
Connection connection = null;
//定义会话
Session session = null;
//目的地
Destination destination = null;
//定义消息的发送者
MessageProducer producer = null;
//定义消息
Message message = null;
try{
/**
* userName:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.properties文件进行修改
* password:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.properties文件进行修改
* brokerURL:访问ActiveMQ服务的路径地址。路径结构为:协议名://主机地址:端口号
*/
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.128:61616");
//创建连接对象
connection = connectionFactory.createConnection();
//启动连接
connection.start();
/**
* transacted:是否使用事务 可选值为:true|false
* true:使用事务 当设置次变量值。Session.SESSION_TRANSACTED
* false:不适用事务,设置次变量 则acknowledgeMode参数必须设置
* acknowledgeMode:
* Session.AUTO_ACKNOWLEDGE:自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE:客户端确认机制
* Session.DUPS_OK_ACKNOWLEDGE:有副本的客户端确认消息机制
*/
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建目的地,目的地名称即队列的名称。消息的消费者需要通过此名称访问对应的队列
destination = session.createQueue("helloworld-destination");
//创建消息的生产者
producer = session.createProducer(destination);
//传递消息
// message = session.createTextMessage(msgTest);
//传递消息对象
message = session.createObjectMessage(msgTest);
//发送消息
producer.send(message);
}catch(Exception e){
e.printStackTrace();
}finally{
//回收消息发送者资源
if(producer != null){
try {
producer.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(session != null){
try {
session.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
HelloWorldProducer producer = new HelloWorldProducer();
Users user = new Users();
user.setAge("11");
user.setName("dzy");
producer.sendHelloWorldActiveMQ(user);
}
consumer(直接获取或者通过监听)
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
public class HelloWorldConsumer {
/**
* 消费消息
*/
public void readHelloWorldActiveMQ() {
// 定义链接工厂
ConnectionFactory connectionFactory = null;
// 定义链接对象
Connection connection = null;
// 定义会话
Session session = null;
// 目的地
Destination destination = null;
// 定义消息的发送者
MessageConsumer consumer = null;
// 定义消息
Message message = null;
try {
/**
* userName:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.
* properties文件进行修改
* password:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.
* properties文件进行修改 brokerURL:访问ActiveMQ服务的路径地址。路径结构为:协议名://主机地址:端口号
*/
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.128:61616");
// 创建连接对象
connection = connectionFactory.createConnection();
// 启动连接
connection.start();
/**
* transacted:是否使用事务 可选值为:true|false true:使用事务
* 当设置次变量值。Session.SESSION_TRANSACTED false:不适用事务,设置次变量
* 则acknowledgeMode参数必须设置 acknowledgeMode:
* Session.AUTO_ACKNOWLEDGE:自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE:客户端确认机制
* Session.DUPS_OK_ACKNOWLEDGE:有副本的客户端确认消息机制
*/
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地,目的地名称即队列的名称。消息的消费者需要通过此名称访问对应的队列
destination = session.createQueue("helloworld-destination");
// 创建消息的消费者
consumer = session.createConsumer(destination);
//第一种获取消息的方法
// 创建消息对象
message = consumer.receive();
//处理消息
// String msg = ((TextMessage)message).getText();
// System.out.println("从ActiveMQ服务中获取的文本信息 "+msg);
//处理对象消息
Users msg1 = (Users)((ObjectMessage)message).getObject();
System.out.println("返回的对象:"+msg1.toString());
//第二种获取消息的方法(监听)
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
//处理消息
String msg = null;
try {
msg = ((TextMessage)message).getText();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("从ActiveMQ服务中获取的文本信息 "+msg);
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
// 回收消息发送者资源
if (consumer != null) {
try {
consumer.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (session != null) {
try {
session.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Test{
public static void main(String[] args) {
HelloWorldConsumer consumer = new HelloWorldConsumer();
consumer.readHelloWorldActiveMQ();
}
}
订阅发布模型
producer
public class HelloWorldProducerTopic {
/**
* 生产消息
*/
public void sendHelloWorldActiveMQ(String msgTest){
//定义链接工厂
ConnectionFactory connectionFactory = null;
//定义链接对象
Connection connection = null;
//定义会话
Session session = null;
//目的地
Destination destination = null;
//定义消息的发送者
MessageProducer producer = null;
//定义消息
Message message = null;
try{
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.128:61616");
//创建连接对象
connection = connectionFactory.createConnection();
//启动连接
connection.start();
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
//创建目的地,目的地名称即队列的名称。消息的消费者需要通过此名称访问对应的队列
destination = session.createTopic("test-topic");
//创建消息的生产者
producer = session.createProducer(destination);
//创建消息对象
message = session.createTextMessage(msgTest);
//发送消息
producer.send(message);
}catch(Exception e){
e.printStackTrace();
}finally{
//回收消息发送者资源
if(producer != null){
try {
producer.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(session != null){
try {
session.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(connection != null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Test {
public static void main(String[] args) {
HelloWorldProducerTopic topic = new HelloWorldProducerTopic();
Users user = new Users();
user.setAge("11");
user.setName("dzy");
topic.sendHelloWorldActiveMQ("tset");
}
}
consumer
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class HelloWorldConsumerTopic implements Runnable{
/**
* 消费消息
*/
public void readHelloWorldActiveMQ() {
// 定义链接工厂
ConnectionFactory connectionFactory = null;
// 定义链接对象
Connection connection = null;
// 定义会话
Session session = null;
// 目的地
Destination destination = null;
// 定义消息的发送者
MessageConsumer consumer = null;
// 定义消息
Message message = null;
try {
/**
* userName:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.
* properties文件进行修改
* password:访问ActiveMQ服务的用户名。用户密码。默认的为admin。用户名可以通过jetty-ream.
* properties文件进行修改 brokerURL:访问ActiveMQ服务的路径地址。路径结构为:协议名://主机地址:端口号
*/
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.128:61616");
// 创建连接对象
connection = connectionFactory.createConnection();
// 启动连接
connection.start();
/**
* transacted:是否使用事务 可选值为:true|false true:使用事务
* 当设置次变量值。Session.SESSION_TRANSACTED false:不适用事务,设置次变量
* 则acknowledgeMode参数必须设置 acknowledgeMode:
* Session.AUTO_ACKNOWLEDGE:自动消息确认机制
* Session.CLIENT_ACKNOWLEDGE:客户端确认机制
* Session.DUPS_OK_ACKNOWLEDGE:有副本的客户端确认消息机制
*/
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地,目的地名称即队列的名称。消息的消费者需要通过此名称访问对应的队列
destination = session.createTopic("test-topic");
// 创建消息的消费者
consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
String msg = null;
try {
msg = ((TextMessage)message).getText();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("从ActiveMQ服务中获取的文本信息 "+msg);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
this.readHelloWorldActiveMQ();
}
}
public class test{
public static void main(String[] args) {
HelloWorldConsumerTopic topic = new HelloWorldConsumerTopic();
Thread t = new Thread(topic);
t.start();
HelloWorldConsumerTopic3 topic1 = new HelloWorldConsumerTopic3();
Thread t1 = new Thread(topic1);
t1.start();
HelloWorldConsumerTopic2 topic2 = new HelloWorldConsumerTopic2();
Thread t2 = new Thread(topic2);
t2.start();
}
}
整合spring
producer pom文件
<dependencies>
<!-- ActiveMQ客户端完整jar包依赖 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
<!-- ActiveMQ和Spring整合配置文件标签处理jar包依赖 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
</dependency>
<!-- Spring-JMS插件相关jar包依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-jms-pool</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
consumer pom文件
<dependencies>
<!-- activemq客户端 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
<!-- spring框架对JMS标准的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<!-- ActiveMQ和spring整合的插件 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
</dependencies>
producer 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:jms="http://www.springframework.org/schema/jms"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 需要创建一个连接工厂,连接ActiveMQ. ActiveMQConnectionFactory. 需要依赖ActiveMQ提供的amq标签 -->
<!-- amq:connectionFactory 是bean标签的子标签, 会在spring容器中创建一个bean对象. 可以为对象命名.
类似: <bean id="" class="ActiveMQConnectionFactory"></bean> -->
<amq:connectionFactory brokerURL="tcp://192.168.3.128:61616"
userName="admin" password="admin" id="amqConnectionFactory" />
<!-- 配置池化的ConnectionFactory。 为连接ActiveMQ的connectionFactory提供连接池 -->
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactoryBean">
<property name="connectionFactory" ref="amqConnectionFactory"></property>
<property name="maxConnections" value="10"></property>
</bean>
<!-- spring管理JMS相关代码的时候,必须依赖jms标签库. spring-jms提供的标签库. -->
<!-- 定义Spring-JMS中的连接工厂对象 CachingConnectionFactory - spring框架提供的连接工厂对象.
不能真正的访问MOM容器. 类似一个工厂的代理对象. 需要提供一个真实工厂,实现MOM容器的连接访问. -->
<!-- 配置有缓存的ConnectionFactory,session的缓存大小可定制。 -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<property name="sessionCacheSize" value="3"></property>
</bean>
<!-- JmsTemplate配置 -->
<bean id="template" class="org.springframework.jms.core.JmsTemplate">
<!-- 给定连接工厂, 必须是spring创建的连接工厂. -->
<property name="connectionFactory" ref="connectionFactory"></property>
<!-- 可选 - 默认目的地命名 -->
<property name="defaultDestinationName" value="test-spring"></property>
</bean>
</beans>
consumer 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:jms="http://www.springframework.org/schema/jms"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- 需要创建一个连接工厂,连接ActiveMQ. ActiveMQConnectionFactory. 需要依赖ActiveMQ提供的amq标签 -->
<!-- amq:connectionFactory 是bean标签的子标签, 会在spring容器中创建一个bean对象.
可以为对象命名. 类似: <bean id="" class="ActiveMQConnectionFactory"></bean>
-->
<amq:connectionFactory brokerURL="tcp://192.168.70.151:61616"
userName="admin" password="admin" id="amqConnectionFactory"/>
<!-- spring管理JMS相关代码的时候,必须依赖jms标签库. spring-jms提供的标签库. -->
<!-- 定义Spring-JMS中的连接工厂对象
CachingConnectionFactory - spring框架提供的连接工厂对象. 不能真正的访问MOM容器.
类似一个工厂的代理对象. 需要提供一个真实工厂,实现MOM容器的连接访问.
-->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<property name="sessionCacheSize" value="3"></property>
</bean>
<!-- 注册监听器 -->
<!-- 开始注册监听.
需要的参数有:
acknowledge - 消息确认机制
container-type - 容器类型 default|simple
simple:SimpleMessageListenerContainer最简单的消息监听器容器,只能处理固定数量的JMS会话,且不支持事务。
default:DefaultMessageListenerContainer是一个用于异步消息监听器容器 ,且支持事务
destination-type - 目的地类型. 使用队列作为目的地.
connection-factory - 连接工厂, spring-jms使用的连接工厂,必须是spring自主创建的
不能使用三方工具创建的工程. 如: ActiveMQConnectionFactory.
-->
<jms:listener-container acknowledge="auto" container-type="default"
destination-type="queue" connection-factory="connectionFactory" >
<!-- 在监听器容器中注册某监听器对象.
destination - 设置目的地命名
ref - 指定监听器对象
-->
<jms:listener destination="test-spring" ref="myListener"/>
</jms:listener-container>
</beans>
consumer消息监听处理
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UserService;
/**
* 娑堟伅鏈嶅姟鐩戝惉鍣�
* @author Administrator
*
*/
@Component(value="myListener")
public class MyMessageListener implements MessageListener{
@Autowired
private UserService userService;
@Override
public void onMessage(Message message) {
//activemq消费者对象
ObjectMessage objMessage = (ObjectMessage)message;
Users user=null;
try {
user = (Users)objMessage.getObject();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.userService.showUser(user);
}
}
producer消息发送
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private JmsTemplate jmsTemplate;
@Override
public void addUser(final Users user) {
this.jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
Message message = session.createObjectMessage(user);
return message;
}
});
}
}