通过前几篇的学习,相信大家已经对我们的ActiveMQ的原生操作已经有了个深刻的概念,

那么这篇文章就来带领大家一步一步学习下ActiveMQ结合Spring的实战操作


注:本文将省略一部分与ActiveMQ无关的spring、mvc等代码,学习者需有SSM框架基础

  所有的注释均写在代码里面,请阅读代码并多多阅读注释!

一 创建生产者

1 所需依赖jar包

     <activemq.version>5.9.0</activemq.version>
<xbean.version>4.5</xbean.version>
<jms.version>4.1.6.RELEASE</jms.version>
<activemq-pool.version>5.9.0</activemq-pool.version>
<!-- ActiveMQ客户端完整jar包依赖 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq.version}</version>
</dependency>
<!-- ActiveMQ和Spring整合配置文件标签处理jar包依赖 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>${xbean.version}</version>
</dependency>
<!-- Spring-JMS插件相关jar包依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${jms.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>${activemq-pool.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-jms-pool</artifactId>
<version>${activemq-pool.version}</version>
</dependency>

2.配置与spring整合的配置文件

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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" /> 所以我们这里边使用简便的方式amq:connectionFactory
-->
<!-- <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://169.254.18.20:61616"/>
<property name="userName" value="admin"/>
<property name="password" value="admin"/>
</bean>-->
<amq:connectionFactory brokerURL="tcp://169.254.18.20:61616"
userName="admin" password="admin" id="amqConnectionFactory"/> <!--
配置池化的ConnectionFactory,为链接ActiveMQ的connectionFactory提供连接池
我们一般不直接用链接工厂,原因是:这个connectionFactory不会复用connection、session、produce
consumer,每次连接都需要重新创建conneciton,再创建session,然后调用session创建新的
producer或者consumer然后用完之后依次关闭,比较浪费资源。
我们一般用这个链接工厂作为其他拥有更高级(缓存)的链接工厂的参数。 又因为PooledConnectionFactory会缓存conneciton,session,producer,不会缓存consumer,所以更适合发送者
-->
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<!--引用上面的链接工厂-->
<property name="connectionFactory" ref="amqConnectionFactory"/>
<!--连接数量-->
<property name="maxConnections" value="10"/>
<!--超时时间,最后使用时间+idleTimeout > 当前时间,连接关闭-->
<property name="idleTimeout" value="30000"/>
<!--回收时间,连接创建时间+expirtyTimeout > 当前时间,连接关闭-->
<property name="expiryTimeout" value="30000"/>
<!--如果连接池是满的,则阻塞-->
<property name="blockIfSessionPoolIsFull" value="true"/>
<!-- 每个链接最大的session(会话)数量-->
<property name="maximumActiveSessionPerConnection" value="10"/>
</bean> <!--
Spring管理JMS相关代码的时候,必须依赖jms标签库、spring-jms提供的标签库 定义Spring-JMS中的连接工厂对象 CachingConnectionFactory -spring框架提供的连接工厂对象
不能真正的访问MOM容器,类似一个工厂的代理对象 需要提供一个真实工厂,实现MOM
容器的连接访问 配置有缓存的ConnectionFactory,session的缓存大小可以指定 默认情况下cachingConnnectionFactory之缓存一个session,针对低并发足够了
-->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"/>
<property name="sessionCacheSize" value="3"/>
</bean> <!-- jmsTemplate 点对点 -->
<bean id="jmsQuequTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 给定连接工厂,必须是spring创建的连接工厂 -->
<property name="connectionFactory" ref="connectionFactory"/>
<!-- 可选 默认目的地命名 -->
<property name="defaultDestinationName" value="test-spring-topic"/>
<!-- 设置消息确认机制-
* * Session.AUTO_ACKNOWLEDGE:自动消息确认机制
* * Session.CLIENT_ACKNOWLEDGE:客户端确认机制
* * Session.DUPS_OK_ACKNOWLEDGE:由副本的客户端确认消息机制
-->
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE"/> <!--开启事务,则Ack无效-->
<!-- <property name="sessionTransacted" value="true"/>--> <!-- 由于receive方法时同步的,所以这里对接收设置超时时间-->
<property name="receiveTimeout" value="60000"/> <!-- 开启订阅 -->
<!-- <property name="pubSubDomain" value="true"/>-->
</bean> <!-- jmsTemplate Topic模式 -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 给定连接工厂,必须是spring创建的连接工厂 -->
<property name="connectionFactory" ref="connectionFactory"/>
<!-- 可选 默认目的地命名 -->
<property name="defaultDestinationName" value="test-spring-topic"/>
<!-- 设置消息确认机制-
* * Session.AUTO_ACKNOWLEDGE:自动消息确认机制
* * Session.CLIENT_ACKNOWLEDGE:客户端确认机制
* * Session.DUPS_OK_ACKNOWLEDGE:由副本的客户端确认消息机制
-->
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE"/> <!--开启事务,则Ack无效-->
<!--<property name="sessionTransacted" value="true"/>-->
<!-- 开启订阅 也就是Topic模式-->
<property name="pubSubDomain" value="true"/>
</bean> <!-- JMSTemplate消息生产者 -->
<bean id="producer" class="cn.arebirth.mq.provider.Producer"/>
</beans>

3 为了松耦合抽取出provider

package cn.arebirth.mq.provider;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator; import javax.annotation.Resource; public class Producer {
@Resource(name = "jmsTopicTemplate")
private JmsTemplate jmsTemplate; /**
* 发送消息
*
* @param destinationName 目的地名称
* @param messageCreator 消息
*/
public void sendMessage(String destinationName, MessageCreator messageCreator) {
if (null != destinationName) {
jmsTemplate.send(messageCreator);
return;
}
jmsTemplate.send(destinationName, messageCreator);
}
}

4 service

通过调用自定义的provider,然后使用了里面的匿名类来创建了一个对象消息,

Uuser为我自己定义的对象,可以任意自定义

package cn.arebirth.service.impl;

import cn.arebirth.mq.provider.Producer;
import cn.arebirth.pojo.Users;
import cn.arebirth.service.UserService;
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 javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session; @Service
public class UserServiceImpl implements UserService { //获取自定义的provider
@Autowired
private Producer producer; @Override
public void addUser(String destinationName, Users user) {
producer.sendMessage(destinationName, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createObjectMessage(user);
}
});
}
}

5 Controller

@Controller
@RequestMapping("/user")
public class UserController { @Autowired
private UserService userService; @RequestMapping("/addUser")
public String addUser(Users user){
this.userService.addUser("test-spring-topic",user);
return "ok";
}
}

然后我们启动tomcat执行,

 由于我们的是Topic模式,所以我们需要在Topic模式里面查看。

出现这样的内容,证明我们的provider发布成功了!

仔细看上面的配置文件我们可以发现

jmsQueueTemplate和jmsTopicTemplate还是有区别的

在我们的topic里面会有这行代码

如果pubSubDomain为true则代表为topic模式,false为queue也就是点对点,我们可以看下源码介绍

/**
* Configure the destination accessor with knowledge of the JMS domain used.
* Default is Point-to-Point (Queues). 默认为点对点也就是queue模式
* <p>This setting primarily indicates what type of destination to resolve
* if dynamic destinations are enabled.
* @param pubSubDomain "true" for the Publish/Subscribe domain ({@link javax.jms.Topic Topics}),
* "false" for the Point-to-Point domain ({@link javax.jms.Queue Queues})
* @see #setDestinationResolver
*/
public void setPubSubDomain(boolean pubSubDomain) {
this.pubSubDomain = pubSubDomain;
} 这是官方代码介绍,默认是queue模式,设置为true的话就是topic模式

二 创建消费者

1 添加pom文件依赖

与provider不同的是,不需要连接池

 <activemq.version>5.9.0</activemq.version>
<xbean.version>4.5</xbean.version>
<jms.version>4.1.6.RELEASE</jms.version>
<!-- ActiveMQ客户端完整jar包依赖 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq.version}</version>
</dependency>
<!-- ActiveMQ和Spring整合配置文件标签处理jar包依赖 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>${xbean.version}</version>
</dependency>
<!-- Spring-JMS插件相关jar包依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${jms.version}</version>
</dependency>

2 整合spring的配置文件

<?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://169.254.18.20:61616"
userName="admin" password="admin" id="amqConnectionFactory"/> <!-- spring管理JMS相关代码的时候,必须依赖jms标签库. spring-jms提供的标签库. -->
<!-- 定义Spring-JMS中的连接工厂对象
CachingConnectionFactory - spring框架提供的连接工厂对象. 不能真正的访问MOM容器.
类似一个工厂的代理对象. 需要提供一个真实工厂,实现MOM容器的连接访问. 默认情况下,cachingConnectionFactory之缓存一个session,对于低并发足以
--> <bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"/>
<property name="sessionCacheSize" value="3"/>
</bean> <!--
注册监听器 DefaultMessageListenerContainer
jms:listener-container 相当于DefaultMessageListenerContainer
负责将messageListener注册到connectionFactory的destination,
一旦destination中有消息,就会将消息推送给messageListener
开始注册监听:
需要的参数有:
acknowledge -消息确认机制
container-type 容器类型 default|simple
simple:SimpleMessageListenerContainer最简单的消息监听容器,只能处理固定数量的JMS会话,而且不支持事务
default:DefaultMessageListenerContainer 是一个用于异步消息监听器容器,且支持事务
destination-type 目的地类型,使用队列作为目的地 queue topic
connection-factory 连接工厂,spring-jms使用的连接工厂,必须是spring自主创建的
不能使用三方工具创建的工程,如:ActiveMQConnectionFactory
-->
<jms:listener-container acknowledge="auto" container-type="default"
destination-type="topic"
connection-factory="connectionFactory">
<!-- 在监听容器中注册某监听器对象
destination -设置目的地命名
ref-指定监听器对象
-->
<jms:listener destination="test-spring-topic" ref="myListener"/> <!--这个myListener是我们自定义的一个监听类,下边代码可以看到-->
</jms:listener-container> </beans>

3 service

很简单就是一个简单输出

package cn.arebirth.service.impl;

import cn.arebirth.pojo.Users;
import cn.arebirth.service.UserService;
import org.springframework.stereotype.Service; @Service
public class UserServiceImpl implements UserService { @Override
public void showUser(Users user) {
System.out.println(user);
} }

4 监听处理消息类Listener

因为我们在配置文件里面已经引用了此对象,我们只需要实现MessageListener消息监听类即可

package cn.arebirth.listener;

import cn.arebirth.pojo.Users;
import cn.arebirth.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage; /**
* 消息服务监听器
*/
@Component(value = "myListener")
public class MyMessageListener implements MessageListener { @Autowired
private UserService userService; @Override
public void onMessage(Message message) {
//处理消息
ObjectMessage objectMessage = (ObjectMessage) message;
Users users = null;
try {
users = (Users) objectMessage.getObject();
} catch (JMSException e) {
e.printStackTrace();
}
this.userService.showUser(users); }
}

5 启动测试

package cn.arebirth;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Start {
public static void main(String[] args) {
String[] content = {"classpath:applicationContext-jms.xml","classpath:applicationContext-service.xml"};
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(content);
context.start();
}
}

启动后,我们发现没有任何消息啊,是不是代码错了啊!

!!我们的是topic模式,所以我们要先启动consumer,然后在进行发布消息,否则,provider发不完可不管你收不收到的

然后我们在重新发布一条消息

内容

我们来看consumer

已经收到消息了,就此我们的整合就已经完毕了


我们的具体精华都在配置文件里面,详细的注释也都在里面,需要多看,并且敲一遍,运行一遍,然后在看一遍,你会有新的收货!

参考博客:

  https://www.cnblogs.com/zackzhuzi/p/10050506.html

ActiveMQ学习总结------Spring整合ActiveMQ 04的更多相关文章

  1. Spring整合ActiveMQ及多个Queue消息监听的配置

        消息队列(MQ)越来越火,在java开发的项目也属于比较常见的技术,MQ的相关使用也成java开发人员必备的技能.笔者公司采用的MQ是ActiveMQ,且消息都是用的点对点的模式.本文记录了实 ...

  2. spring整合ActiveMq

    spring整合ActiveMq: 1:依赖的jar包: 2:spring-activemq.xml    的配置: 代码: <?xml version="1.0" enco ...

  3. 【报错】spring整合activeMQ,pom.xml文件缺架包,启动报错:Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

    spring版本:4.3.13 ActiveMq版本:5.15 ======================================================== spring整合act ...

  4. Spring整合ActiveMQ实现消息延迟投递和定时投递

    linux(centos)系统安装activemq参考:https://www.cnblogs.com/pxblog/p/12222231.html 首先在ActiveMQ的安装路径 /conf/ac ...

  5. ActiveMQ学习总结(3)——spring整合ActiveMQ

    1.参考文献 Spring集成ActiveMQ配置 Spring JMS异步发收消息 ActiveMQ 2.环境 在前面的一篇ActiveMQ入门实例中我们实现了消息的异步传送,这篇博文将如何在spr ...

  6. spring 整合 ActiveMQ

    1.1     JMS简介 JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到 ...

  7. Java消息队列-Spring整合ActiveMq

    1.概述 首先和大家一起回顾一下Java 消息服务,在我之前的博客<Java消息队列-JMS概述>中,我为大家分析了: 消息服务:一个中间件,用于解决两个活多个程序之间的耦合,底层由Jav ...

  8. Spring整合ActiveMq消息队列

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ...

  9. activeMq-3 Spring整合activeMq

    与jdbcTemplate相似的是,Spring也提供了JmsTemplate 生产者使用JmsTemplate生产消息,消费者实现一个监听器用于获取消息 项目用maven构建,jdk1.8, 文末提 ...

随机推荐

  1. 《Java基础知识》Java类的定义及其实例化

    类必须先定义才能使用.类是创建对象的模板,创建对象也叫类的实例化. 下面通过一个简单的例子来理解Java中类的定义: public class Dog { String name; int age; ...

  2. 微服务架构 SpringBoot(二)

    第二天内容:想来想去玩个ssm小demo吧 1.创建表 2..引入相关mybatis 数据库jar: <!--mybatis --> <dependency> <grou ...

  3. 域控权限提升PTH攻击

    0x01 漏洞利用条件 1.被pth攻击的计算机未打补丁(KB2871997)2.拿到一台域成员主机并且拿到管理员组的域用户的NTML 3.对方主机存在相同账号并且是管理员组成员 0x02 本地用户N ...

  4. adb 获取平台号

    获取 Android 的 PLATFORM_VERSION :adb shell getprop ro.build.version.release获取 Android 的 APP_PACKAGE 和 ...

  5. 面试连环炮系列(八):服务器CPU飙升100%怎么排查

    服务器CPU飙升100%怎么排查 执行"top"命令,查看当前进程CPU占用的实时情况,PID列是进程号,确定是哪个应用程序的问题. 如果是Java应用导致的,怎么定位故障原因 执 ...

  6. Appium+Java 自动化测试系列一:环境搭建

    Appium+Java 自动化测试框架搭建主要分为以下几个方面的下载安装及环境配置 1.Java开发环境 涉及到的内容又jdk.编译器工具(推荐jdk 1.8.Eclipse编译器或者IDEA编译工具 ...

  7. SpringBoot源码篇:Spring5内置tomcat实现code-based的web.xml实现

    一.简介 上篇文章讲了SpingBoot诞生的历史背景和技术演进背景,并通过源码说明了SpringBoot是如何实现零配置的包括如何省去web.xml配置的原理.本文接上一篇文章,通过demo演示Sp ...

  8. Prometheus学习系列(九)之Prometheus 存储

    前言 本文来自Prometheus官网手册 和 Prometheus简介 存储 Prometheus是一个本地磁盘时间序列数据库,但也可选择与远程存储系统集成,其本地时间序列数据库以自定义格式在磁盘上 ...

  9. node、npm、chrome、v8、sandbox是什么?

    这些东西有些比较常用,有些仅知道个名称,但无论是熟悉还是陌生的,要比较精确地解释这些东西,是有一定的难度,可这些东西对前端开发非常重要,还是需要有明确的概念. PS:内容点到即止,不然一个东西一篇文章 ...

  10. html5的 history模式和hash模式

    直观区别 hash 带一个# history 没有# 各自特点 hash: 仅 hash 符号之前的内容会被包含在请求中,**因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误.* ...