SpringBoot中使用AMQ的两种方式(Java配置、注解方式)

                                       Java配置方式使用AMQ


1. 引入依赖(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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.5.8.RELEASE</version>
  </parent>
  
  <groupId>org.hik.hyy</groupId>
  <artifactId>homework_boot</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>homework_boot Maven Webapp</name>
  
  <dependencies>
     	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- springboot操作数据库依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- mysql连接驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        
 		<dependency>  
			<groupId>org.springframework</groupId>  
			<artifactId>spring-webmvc</artifactId>  
   		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>javax.servlet-api</artifactId>
		    <scope>provided</scope>
		</dependency>
   		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		</dependency>
 		<!-- freemarker模板引擎视图 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- jsp解析器 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>

 
        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        
        <!-- 引入StringUtils工具类 -->
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.5</version>
		</dependency>
		<!-- 切面 -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aop</artifactId>
		    </dependency>
		<!-- 日志包 -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-api</artifactId>
		    </dependency>
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-log4j12</artifactId>
		    <scope>test</scope>
		</dependency>
		
		<!-- JMS-Activemq -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jms</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
		</dependency>
		<dependency>
              <groupId>org.apache.activemq</groupId>
              <artifactId>activemq-all</artifactId>
              <version>5.11.2</version>
         </dependency>
  </dependencies>
  <build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- 资源文件拷贝插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<!-- maven启动插件 spring-boot:run -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!-- 配置Tomcat插件 -->
				<plugin>
					<groupId>org.apache.tomcat.maven</groupId>
					<artifactId>tomcat7-maven-plugin</artifactId>
					<version>2.2</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

2. 编写配置类(JMSConfig、AMQConfig)

     萌新刚开始使用springboot,我在测试的使用使用两个test方法加载同一个SpringApplication容器,又因为MessageListenerContainer又写在了这个配置类中,导致接收方法接收消息的时候发现消息“丢失”了(发送方法的test也接收到了消息),所以这里写两个配置类,内容起始都是一样的,只不过让发送的方法、接收方法加载两个不同的容器。

         2.1JMSConfig(发送方法加载)

package com.hik.hyy.config;


import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jms.connection.SingleConnectionFactory;
import org.springframework.jms.core.JmsTemplate;

@SpringBootConfiguration
@PropertySource(value = {"classpath:db.properties"}, ignoreResourceNotFound = true)
public class JmsConfig {

	@Value("${brokerURL}")
	private String brokerURL;
	
	@Value("${queue.name}")
	private String queue;
	
	@Value("${topic.name}")
	private String topic;
	
	//真正可以产生Connection的ConnectionFactory,即ActiveMq创建的 
	@Bean
	public ActiveMQConnectionFactory activeMQConnectionFactory(){
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
		activeMQConnectionFactory.setBrokerURL(brokerURL);
		return activeMQConnectionFactory;
	}
	//配置Spring管理的ConnectionFactory
	@Bean
	public SingleConnectionFactory singleConnectionFactory(){
		//目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory
		SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory(activeMQConnectionFactory());
		return singleConnectionFactory;
	}
	//Spring提供的JMS模板类,用于消息发送、接收等
	@Bean
	public JmsTemplate jmsTemplate(){
		JmsTemplate jmsTemplate = new JmsTemplate();
		jmsTemplate.setConnectionFactory(singleConnectionFactory());
		return jmsTemplate;
	}
	//这个是queue目的地,点对点的
	@Bean
	public ActiveMQQueue queueDestination(){
		ActiveMQQueue activeMQQueue = new ActiveMQQueue(queue);
		return activeMQQueue;
	}
	//这个是topic目的地,一对多的
	@Bean
	public ActiveMQTopic topicDestination(){
		ActiveMQTopic activeMQTopic = new ActiveMQTopic(topic);
		return activeMQTopic;
	}
		
}

db.properties(里面配置数据库等信息,懒癌比较严重所以就写里面了)

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/homework?characterEncoding=UTF-8&useSSL=false
jdbc.username=root
jdbc.password=root

#ActiveMq
brokerURL=tcp://10.20.81.118:61616
queue.name=hyy-queue
topic.name=hyy-topic

           2.2AMQConfig(接收方法加载的)

                先编写接收消息的监听类MyMessageListener

package com.hik.hyy.jms.mvcMQ;

import java.util.Optional;

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

public class MyMessageListener implements MessageListener{

	@Override
	public void onMessage(Message message) {
		try {
			//练习下Optional的使用
			Optional<TextMessage> textOpt = Optional.ofNullable((TextMessage)message);
			if (textOpt.isPresent()) {
				System.err.println(textOpt.get().getText());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

             接着编写配置类AMQConfig

 

package com.hik.hyy.config;


import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jms.connection.SingleConnectionFactory;
import org.springframework.jms.core.JmsTemplate;

@SpringBootConfiguration
@PropertySource(value = {"classpath:db.properties"}, ignoreResourceNotFound = true)
public class JmsConfig {

	@Value("${brokerURL}")
	private String brokerURL;
	
	@Value("${queue.name}")
	private String queue;
	
	@Value("${topic.name}")
	private String topic;
	
	//真正可以产生Connection的ConnectionFactory,即ActiveMq创建的 
	@Bean
	public ActiveMQConnectionFactory activeMQConnectionFactory(){
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
		activeMQConnectionFactory.setBrokerURL(brokerURL);
		return activeMQConnectionFactory;
	}
	//配置Spring管理的ConnectionFactory
	@Bean
	public SingleConnectionFactory singleConnectionFactory(){
		//目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory
		SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory(activeMQConnectionFactory());
		return singleConnectionFactory;
	}
	//Spring提供的JMS模板类,用于消息发送、接收等
	@Bean
	public JmsTemplate jmsTemplate(){
		JmsTemplate jmsTemplate = new JmsTemplate();
		jmsTemplate.setConnectionFactory(singleConnectionFactory());
		return jmsTemplate;
	}
	//这个是queue目的地,点对点的
	@Bean
	public ActiveMQQueue queueDestination(){
		ActiveMQQueue activeMQQueue = new ActiveMQQueue(queue);
		return activeMQQueue;
	}
	//这个是topic目的地,一对多的
	@Bean
	public ActiveMQTopic topicDestination(){
		ActiveMQTopic activeMQTopic = new ActiveMQTopic(topic);
		return activeMQTopic;
	}
	//注册MessageListener
	@Bean
	public MyMessageListener myMessageListener(){
		return new MyMessageListener();
	}
	//消息监听器
	@Bean
	public DefaultMessageListenerContainer defaultMessageListenerContainer(){
		DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
		container.setConnectionFactory(singleConnectionFactory());
		//监听queue
		container.setDestination(queueDestination());
		//监听topic
//		container.setDestination(topicDestination());
		container.setMessageListener(myMessageListener());	
		return container;
	}
		
}

这里说明下,如果要监听topic的话,container.setMessageListener()方法里面的对象切换下。

3. 编写测试方法

package com.hik.hyy.jms.mvcMQ;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.hik.hyy.config.AMQConfig;
import com.hik.hyy.config.JmsConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {JmsConfig.class}) //必须要有,不然Failed to load ApplicationContext
   //@ContextConfiguration(classes = {JmsConfig.class,AMQConfig.class}) 这样配置会导致发消息的时候,自己也能监听到
public class ActiveMQTest {

	//加载模板类
	@Autowired
	private JmsTemplate jmsTemplate;
	private ApplicationContext applicationContext;
	
	/** 
	* @Description:  队列消息生产者
	* @param @throws Exception    
	* @return void
	* @date: 2018年9月26日 下午4:22:43  
	* @throws 
	*/
	@Test
	public void testQueueProducer() throws Exception{
		//加载生产者的配置类
		applicationContext = new AnnotationConfigApplicationContext(JmsConfig.class);
		Queue queue = (Queue) applicationContext.getBean("queueDestination");
		for (int i = 0; i < 5; i++) { //生产五条消息
			jmsTemplate.send(queue, new MessageCreator() {
				@Override
				public Message createMessage(Session session) throws JMSException {
					TextMessage message = session.createTextMessage("hello,this is a queueMessage");
					return message;
				}
			});
		}
	}
	
	/** 
	* @Description:  主题消息生产者
	* @param @throws Exception    
	* @return void
	* @date: 2018年9月26日 下午4:23:13  
	* @throws 
	*/
	@Test
	public void testTopicProducer() throws Exception{
		//加载生产者的配置类
		applicationContext = new AnnotationConfigApplicationContext(JmsConfig.class);
		Topic topic = (Topic) applicationContext.getBean("topicDestination");
		for (int i = 0; i < 5; i++) { //生产5条消息
			jmsTemplate.send(topic, new MessageCreator() {
				
				@Override
				public Message createMessage(Session session) throws JMSException {
					TextMessage message = session.createTextMessage("hello,this is a topicMessage");
					return message;
				}
			});
		}
	}
	
	/** 
	* @Description:  消费者
	* @param @throws Exception    
	* @return void
	* @author: huyuyuan
	* @date: 2018年9月26日 下午4:24:02  
	* @throws 
	*/
	@Test
	public void testConsumer() throws Exception{
		//这里加载消费配置类
		applicationContext = new AnnotationConfigApplicationContext(AMQConfig.class);
		System.in.read();
	}
		
}

4. 结果

          4.1queue

             运行testQueueProducer()方法:

             再运行testConsumer()方法

          这也说明在点对点模式中,消费者和生产者并没有时间上的关联,并且是一对一的消费,具体的话,将生产者加载的配置类改成跟消费者一样, 最后会发现生产者和消费者受到的消息总数跟发送者发出的是相等的(之前我以为是消息丢失的缘故)

       4.2 topic

            为了体现多个订阅者都能监听到消息,我们将生产者加载的配置类改成跟消费者一样的配置:

@Test
	public void testTopicProducer() throws Exception{
		//加载生产者的配置类
        //加载消费者配置类,验证一个主题消息可以被多个消费者消费
		applicationContext = new AnnotationConfigApplicationContext(AMQConfig.class);  
		Topic topic = (Topic) applicationContext.getBean("topicDestination");
		for (int i = 0; i < 5; i++) { //生产5条消息
			jmsTemplate.send(topic, new MessageCreator() {
				
				@Override
				public Message createMessage(Session session) throws JMSException {
					TextMessage message = session.createTextMessage("hello,this is a topicMessage");
					return message;
				}
			});
		}
	}

运行testConsumer()方法启动监听,再运行testTopicProducer()发送消息,

反之,如果先运行生产者方法,生产者能够接收到消息,但消费者就接收不到了消息了

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值