JMS消息服务入门讲解,SpringBoot集成ActiveMQ的实现【集成篇】

接上一篇JMS基础篇,现在我们将ActiveMQ与SrpingBoot集成一下,如果读者还没有了解JMS是什么的话,请先去看基础篇呗。SpringBoot提供了很便捷方法供去调用JMS。在实际项目中,通过生产者和消费者会是两个独立的应用工程, 也正是如此通过消息队列实现了解耦和广播,考虑到仅仅案例使用,本案例将两者放置在一个工程应用。

 

一、环境搭建

基础环境:SpringBoot+Maven+ActiveMQ,截一张项目目录图

搭建SpringBoot、Maven、ActiceMQ(在基础篇有详细说明)的过程,我就不在这里诉述了,这里主要讲集成吧

①.创建好基于SpringBoot的工程之后,在pom.xml中引入ActiveMQ包:



    org.springframework.boot
    spring-boot-starter-activemq

②.在SpringBoot的工程的配置文件[application.properties]中添加(也可以零配置,在配置类里进行配置):

#jms--ActiveMQ
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.pool.enabled=false

③.添加关于ActionMQ的相关spring支持的bean,这里给出相关的启动加载的配置spring容器信息,关于ActionMQ的一些配置信息,在基础篇有提到,这里就不详述了。

package com.cheng.sbjm.configure;
import javax.jms.Queue;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.cheng.sbjm.security.LoginStatusInterceptor;

/**
 * file:CustomWebMvcConfigurerAdapter.java
 * @author ouyang
 * 增加MVC的拦截器
 */

@Configuration //注解为此class为一个配置类
@EnableJms
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter{

	@Override
	public void addInterceptors (InterceptorRegistry registry){
		
		registry.addInterceptor(new LoginStatusInterceptor()).addPathPatterns("/**");
	}

	/**
	 * 浏览器跨域请求处理,允许所有域名下发起的请求
	 * @return
	 */
	 @Bean
	 public CorsFilter corsFilter() {
		 final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
		 final CorsConfiguration corsConfiguration = new CorsConfiguration();
		 corsConfiguration.setAllowCredentials(true);
		 corsConfiguration.addAllowedOrigin("*");
		 corsConfiguration.addAllowedHeader("*");
		 corsConfiguration.addAllowedMethod("*");
		 urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
		 return new CorsFilter(urlBasedCorsConfigurationSource);
	 }
	 
	 @Bean  
	    public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory,Queue queue){  
	        JmsTemplate jmsTemplate=new JmsTemplate();  
	        jmsTemplate.setDeliveryMode(2);//进行持久化配置 1表示非持久化,2表示持久化
                activeMQConnectionFactory.setTrustAllPackages(true);//使用实体直接入队时配置,字符串入队列,不需要,为了演示将整个实体件入队传输。
	        jmsTemplate.setConnectionFactory(activeMQConnectionFactory);  
	        //jmsTemplate.setDefaultDestination(queue); //此处可不设置默认,在发送消息时也可设置队列  
	        jmsTemplate.setSessionAcknowledgeMode(1);//客户端签收模式 
	        return jmsTemplate;  
	 	}
}

 

至此,关于springBoot与ActiveMQ的集成配置已经完成(太TN简单了!),接下来,我们来写demo来演示:

 

1.启动ActiveMQ的容器(具体步骤移步到基础篇哦)

2.编写消息生产者(包括点对点和话题)

package com.cheng.sbjm.service.Imp;

import javax.jms.*;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.cheng.sbjm.service.JmsProducerService;

/**
 * 消息生产者
 */
@Service
public class JmsProducerServiceImpl implements JmsProducerService {

	@Autowired // 也可以注入JmsTemplate,JmsMessagingTemplate对JmsTemplate进行了封装  
        private JmsMessagingTemplate jmsTemplate; 

        @Autowired
        private JmsTemplate jmsTemplate;
	
	/**
	 * 1生产者发送消息(发送信息到队列)
	 * 根据实例化Destination目的地参数的类型的对象决定是点对点队列的形式,还是广播的形式
	 * 
	 */
	@Scheduled(fixedRate = 5000)
	@Override
	public void queueSend() {
		
	//定义一个目的地(队列类型)
        Destination queue = new ActiveMQQueue("mytest.queue");  
        jmsTemplate.convertAndSend(queue, "myname is Oyzc");
	
		
	}
	/**
	 * 2生产者发送消息(发送信息到话题)
	 * 
	 */
	@Scheduled(fixedRate = 5000)
	@Override
	public void topicSend() {
		
		//定义一个目的地(队列类型)
		Destination topic = new ActiveMQTopic("mytest.topic"); 
                jmsTemplate.convertAndSend(topic, "myname is Oyzc");
	}
	

	/**
	 * 3生产者发送出去消息之后,可以马上监听指定消费者的反馈信息
	 * @param text
	 */
	@Override
	@JmsListener(destination="out.queue")
	public void consumerMessage(String text) {
		
		System.out.println("从out.queue队列收到的回复报文为:"+text);
		
	}
	/**
     * 另外一种队列发送方式(直接传输实体)
     * @param
     */
    @Scheduled(fixedRate = 5000)
    @Override
    public void queueSend2() {

        final UserRequest user=new UserRequest();
        user.setUserName("ouyzc");
        user.setPhone("123456789");

        jmsTemplate.send("queue.lytest",new MessageCreator(){
            @Override
            public Message createMessage(Session session) throws JMSException {
                System.out.println("发送队列!!");
                return session.createObjectMessage(user);
            }
        });

    }

    /**
     * 另外一种队列发送方式(传输JSON字符串)
     * @param
     */
    @Scheduled(fixedRate = 5000)
    public void sendQueueJson(){
        UserRequest user=new UserRequest();
        user.setUserName("ouyzc");
        user.setPhone("123456789");
        String requestJson= JSON.toJSONString(user);
        Destination queue = new ActiveMQQueue("json.queue");
        jmsMessageingTemplate.convertAndSend(queue,requestJson);
    }
	

}

 

消息生产者已经编写完成,发现点对点和话题的代码不同之处只是实例化对象不同,涉及的几个工具类。

 

@Scheduled(fixedRate = 5000):为了测试,定时执行5S

JmsMessagingTemplate:封装了对JMS的具体操作

Destination queue = new ActiveMQQueue("mytest.queue");  定义队列,参数为队列名称

Destination topic = new ActiveMQTopic("mytest.topic"); 定义话题,参数为话题名称

JmsMessagingTemplate.convertAndSend(topic, "myname is Oyzc"):转化并发送队列/话题信息(第一个参数为目的地,就是上面定义的队列/话题,第二个参数是发送的内容,可以是字符串也可以是实体,不过我一般是把实体转化成JSON字符串来传输)。

这里顺便给一个JSON字符操作(阿里的)工具类:

 

    com.alibaba
    fastjson
    1.2.3
//bean转化成json字符串
String requestJson= JSON.toJSONString(user);

 

 

 

3.编写消息消费者(包括点对点和话题)

package com.cheng.sbjm.service.Imp;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Service;
import com.cheng.sbjm.service.JmsConsumerService;
import javax.jms.*;
/**
 * 消息消费者
 */
@Service
public class JmsConsumerServiceImpl implements JmsConsumerService{

	// 使用JmsListener配置消费者监听的队列,其中text是接收到的消息
	
	/**
	 * 消费者接收信息1(接收队列为mytest.queue的信息,并马上回复信息到out.queue队列中)
	 */
	@Override
	// 使用JmsListener配置消费者监听的队列,其中text是接收到的消息  
        @JmsListener(destination = "mytest.queue") 
	@SendTo("out.queue")  
	public String receiveQueue1(String text) {
		
		System.out.println("消费者1收到目的地为mytest.queue发来的信息"+text);	
		
		return "mytest.queue接收到你的信息了";
	}
	/**
	 * 消费者接收信息2(先订阅mytest.topic话题,后接收话题为mytest.topic的信息)
	 */
	@Override
        @JmsListener(destination = "mytest.topic") 
	public void receiveTopic2(String text) {
		
		System.out.println("消费者2收到话题为mytest.topic发来的信息"+text);	
		
	}
	
	/**
	 * 消费者接收信息3(先订阅mytest.topic话题,后接收话题为mytest.topic的信息)
	 */
	@Override
        @JmsListener(destination = "mytest.topic") 
	public void receiveTopic3(String text) {
		
		System.out.println("消费者3收到话题为mytest.topic发来的信息"+text);	
		
	}

        @Override
        @JmsListener(destination = "queue.lytest")
        public void receiveQueue2(Message message) {
            if(message instanceof ObjectMessage){
                ObjectMessage objectMessage=(ObjectMessage)message;
                try{
                    UserRequest request=(UserRequest) objectMessage.getObject();
                    System.out.println("接收队列!!");
                    System.out.println(request.getUserName());
                    System.out.println(request.getPhone());
                }catch (Exception e){

                    System.out.println("接收队列失败!!"+e.getMessage());
                }
            }
        }

        @JmsListener(destination = "json.queue")
            public void receiveQueueJson(String requestJson){
                System.out.println("接收队列:"+requestJson);
                UserRequest request= JSON.parseObject(requestJson,UserRequest.class);
                System.out.println(request.getUserName());
                System.out.println(request.getPhone());
            }
	
}
//json字符串转化成bean
UserRequest request= JSON.parseObject(requestJson,UserRequest.class);

消息消费者已经编写完成,涉及的几个注解。

 

@JmsListener(destination = "mytest.queue") :开启异步监听,监听名称为“mytest.queue”的队列/话题

@SendTo("out.queue") :返回消息给名称为“out.queue”的队列

这里为了方便测试,消息消费2和3都是接收同一个话题的消息

 

4.测试

利用springBoot内置的Tomcat启动工程,查看控制台发现

队列是成功发送和反馈信息了,但是话题怎么没发送呢?不急,ActiveMQ默认只打开point to point方式。

到配置文件[application.properties]中添加:

spring.jms.pub-sub-domain=true

再启动,查看控制台发现

话题也成功发送和接收了,但是队列的信息却没有,原来目前ActiveMQ只支持一种类型。

看一下ActiveMQ提供的监控

想2种同时使用的话,楼主还有待验证.......

好了,SpringBoot和ActiveMQ的集成入门篇就到这里,各位可以根据各自的业务需求,进行修改和连接前端和数据库,这只是最简单的demo,后面如果还有涉及其他真正的使用,我还会上一些真正的实例。如有错漏,请各位大神指点!

 

你可能感兴趣的:(消息中间件)