Java中间件JMS(四)之ActiveMQ整合spring之类转换(三)

前几章都是直接发送MapMessage类型的数据,拿前面的例子来讲,如果生产者发送的是TextMessage,消费者也是必须TextMessage;如果我们自己要发送的数据不是TextMessage类型,而消费者还是TextMessage的,那该怎么办?难道每次接受后都要增加一个转换方法么?其实spring早就考虑到这种情况了。转化器在很多组件中都是必不缺少的东西Spring的MessageConverter接口提供了对消息转换的支持。

1、转换类的相关代码POJO

新建一个类MsgPoJo,就是一个简单的Pojo类。具体代码如下:

package jms.mq.spring;

import java.io.Serializable;

public class MsgPoJo implements Serializable{
	private String id;
	private String text;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}	
}


2.转换类的实现

新建一个类MsgConverter.java,实现MessageConverter接口。生成的代码如下

package jms.mq.spring;

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

import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;

public class MsgConverter implements MessageConverter{

	@Override
	public Object fromMessage(Message message) throws JMSException,
	MessageConversionException {
		if (!(message instanceof TextMessage)) {
			throw new MessageConversionException("Message is not TextMessage");
		}
		System.out.println("--转换接收的消息--");
		TextMessage textMessage = (TextMessage) message;
		MsgPoJo msgPojo = new MsgPoJo();
		String[] texts=textMessage.getText().split(",");
		msgPojo.setId(texts[0]);
		msgPojo.setText(texts[1]);
		return msgPojo;
	}

	@Override
	public Message toMessage(Object object, Session session) throws JMSException,
	MessageConversionException {
		if (!(object instanceof MsgPoJo)) {
			throw new MessageConversionException("obj is not MsgPojo");
		}
		System.out.println("--转换发送的消息--");
		MsgPoJo msgPojo = (MsgPoJo) object;
		TextMessage textMessage = session.createTextMessage();
		textMessage.setText(msgPojo.getId()+","+msgPojo.getText());
		return  textMessage;
	}
}

代码很简单就是做些转换,有fromMessage和toMessage两个方法,真好对应发送转换toMessage和接受转换fromMessage。此时,发送和接收消息要换成template.convertAndSend(message);template.receiveAndConvert()。接下来我做一些配置,让spring知道我们的转换类。修改applicationContext.xml中jms模版配置的代码,修改后的代码如下:

	<!-- 类转换 -->
	<bean id="msgConverter" class="jms.mq.spring.MsgConverter"></bean>
	
	<!-- 配置Jms模板 -->
	<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="queueDest" />
		<!--<property name="receiveTimeout" value="10000" /> -->
		<!-- 类转换 -->
		<property name="messageConverter" ref="msgConverter"></property>
	</bean>

注意:如果你有队列监听容器配置,配置jmsQueueTemplate和jmsTopicTemplate可能与队列容器配置冲突。

3、业务相关代码和配置

在QueueProducerService.java增加convertAndSend()方法并在其实现类中实现,实现类的代码如下:

package jms.mq.spring;

import java.util.Date;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class QueueProducerService{
	JmsTemplate jmsTemplate;

	Destination destination;

	public void send() {
		MessageCreator messageCreator = new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				TextMessage message = session.createTextMessage();
				message.setText("QueueProducerService发送消息"+new Date());
				return message;
			}

		};
		jmsTemplate.send(this.destination,messageCreator);
	}
	
	public void convertAndSend(){
		MsgPoJo msgPojo = new MsgPoJo();
		msgPojo.setId("1");
		msgPojo.setText("first msg");
		System.out.println("--发送消息:msgPojo.id为"+msgPojo.getId()+";msgPojo.text为"+msgPojo.getText());
		jmsTemplate.convertAndSend(this.destination, msgPojo);
	}


	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}
	
	public void setDestination(Destination destination) {
		this.destination = destination;
	}
}

同样在QueueConsumerService.java中增加receiveAndConvert()方法并在其实现类中实现,实现类的代码如下:

package jms.mq.spring;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.TextMessage;
import org.springframework.jms.core.JmsTemplate;


public class QueueConsumerService{

	JmsTemplate jmsTemplate;

	Destination destination;

	public void receive() {
		TextMessage message = (TextMessage) jmsTemplate.receive();
		try {
			System.out.println("QueueConsumerService收到消息:"+message.getText());

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

	public void receiveAndConvert() {
		MsgPoJo msgPojo = (MsgPoJo)jmsTemplate.receiveAndConvert();
		if(msgPojo!=null){
			System.out.println("--收到消息:msgPojo.id为"+msgPojo.getId()+";msgPojo.text为"+msgPojo.getText());
		}
	}

	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	public void setDestination(Destination destination) {
		this.destination = destination;
	}
}

修改我们的两个测试类,增加对转换方法的调用,不再赘述,直接上代码:

QueueConsumerTest.java测试类

package jms.mq.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class QueueConsumerTest {
	private static ApplicationContext appContext = new ClassPathXmlApplicationContext( "applicationContext.xml");

	private static void receive() {
		QueueConsumerService consumerService = (QueueConsumerService) appContext.getBean("queueConsumerService");
		consumerService.receive();
	}

	private static void receiveAndConvert() {
		QueueConsumerService consumerService = (QueueConsumerService) appContext.getBean("queueConsumerService");
		consumerService.receiveAndConvert();
	}


	public static void main(String[] args) {
		//receive();
		receiveAndConvert();
	}
}

QueueProducerTest.java测试类

package jms.mq.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class QueueProducerTest {
	private static ApplicationContext appContext = new ClassPathXmlApplicationContext( "applicationContext.xml");

	private static void send() {
		QueueProducerService producerService = (QueueProducerService) appContext.getBean("queueProducerService");
		producerService.send();
	}
	
	private static void convertAndSend() {
		QueueProducerService producerService = (QueueProducerService) appContext.getBean("queueProducerService");
		producerService.convertAndSend();
	}

	public static void main(String[] args) {
		//send();
		convertAndSend();
	}

}

代码编写完毕,我们看一下我们的劳动成果。首先运行生产者类和消费者控制台信息如下:



收到的内容与发的内容相同,说明转换成功了。如果这一部分的程序使用的队列跟上面的一样,那你会发现发送的时候打印出的信息不值上面的一个,还包括一个接收的信息,这是为什么呢?了解spring原理的人应该知道,spring是把所有类都加载到内容中,当然也包括我们上门写的按个实现MessageListener的一个消费者类,他们也在运行,如果监听的地址跟你送的地址正好相同的话,他也有可能收到这个信息。所以在测试的时候要注意修改配置文件。

	<bean id="queueProducerService" class="jms.mq.spring.QueueProducerService">
		<property name="jmsTemplate" ref="jmsQueueTemplate" />
		<property name="destination" ref="queueDest" />  
	</bean>

	<bean id="queueConsumerService" class="jms.mq.spring.QueueConsumerService">
		<property name="jmsTemplate" ref="jmsQueueTemplate" />
		<property name="destination" ref="queueDest" /> 
	</bean>

4、监听器上的使用方式

我再来学习一下跟监听器联合使用的方式,只在发布订阅者模式上演示一下。我们先来修改发布者的实现方式,在发布者中增加convertAndSend方法并在其实现类中实现,订阅者监听器没有类转换,不用修改,发布者修改后的代码如下:

package jms.mq.spring;

import java.util.Date;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import jms.spring.QueueProducerService;

public class TopicPublisherService{
	JmsTemplate jmsTemplate;
	 
	Destination destination;

	public void send() {
		MessageCreator messageCreator = new MessageCreator() {

			public Message createMessage(Session session) throws JMSException {
				TextMessage message = session.createTextMessage();
				message.setText("QueueProducerService发送消息"+new Date());
				return message;
			}
		};
		jmsTemplate.send(this.destination,messageCreator);
	}

	public void convertAndSend(Object obj) {
		System.out.println("--发送PoJo对象...");
		jmsTemplate.convertAndSend(destination, obj);
	}

	
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	public void setDestination(Destination destination) {
		this.destination = destination;
	}

}

发布订阅者配置文件如下

	<!-- 配置TopicJms模板 -->
	<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="topicDest" />
		<!-- 配置是否为发布订阅者模式,默认为false -->
		<property name="pubSubDomain" value="true" />
		<!--<property name="receiveTimeout" value="10000" /> -->
		<property name="messageConverter" ref="msgConverter"></property>
	</bean>
<bean id="topicPublisherService" class="jms.mq.spring.TopicPublisherService">
		<property name="jmsTemplate" ref="jmsTopicTemplate" />
		<!-- <property name="destination" ref="topicDest" /> -->
		<property name="destination" ref="topicSubscriberMessageListenerDest" /> 
	</bean>

	<bean id="topicSubscriberService" class="jms.mq.spring.TopicSubscriberService">
		<property name="jmsTemplate" ref="jmsTopicTemplate" />
		<property name="destination" ref="topicDest" />
	</bean>

修改上面的发布测试类,修改增加对新增方法的调用,修改后的内容如下:

package jms.mq.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TopicPublisherTest {
	private static ApplicationContext appContext = new ClassPathXmlApplicationContext( "applicationContext.xml");

	private static void send() {
		TopicPublisherService topicPublisherService = (TopicPublisherService) appContext.getBean("topicPublisherService");
		topicPublisherService.send();
	}
	private static void convertAndSend() {
		TopicPublisherService topicPublisherService = (TopicPublisherService) appContext.getBean("topicPublisherService");
		MsgPoJo msgPoJo = new MsgPoJo();
		msgPoJo.setId("1");
		msgPoJo.setText("测试内容");
		topicPublisherService.convertAndSend(msgPoJo);
	}


	public static void main(String[] args) {
		//send();
		convertAndSend();
	}
}

运行发布测试类,运行结果如下:


写在到这里,ActiveMQ与spring整合就讲完了,主要讲了ActiveMQ与spring的简单整合,监听器和类转换这些主要功能.

呵呵,写到不好,请大家不要拍砖。




  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
JMS工厂(JMS Connection Factory)是JMS规范中的概念,它是用来创建JMS Connection(即JMS连接)的工厂。在使用JMS时,我们需要先创建一个JMS连接,然后使用这个连接来创建JMS会话(JMS Session),最后使用JMS会话来发送和接收JMS消息。 针对不同的JMS消息中间件,我们需要使用不同的JMS Connection Factory。在使用ActiveMQ时,我们可以使用ActiveMQ提供的ActiveMQConnectionFactory来创建JMS连接。 而在Spring JMS框架中,我们可以使用Spring提供的ConnectionFactory来创建JMS Connection Factory。Spring提供了多个ConnectionFactory的实现,例如: - ActiveMQConnectionFactory:用于创建ActiveMQJMS Connection Factory。 - CachingConnectionFactory:用于创建基于缓存的JMS Connection Factory。 - SingleConnectionFactory:用于创建单例的JMS Connection Factory。 在Spring Boot中,我们可以通过配置文件来配置JMS Connection Factory,例如: ``` spring.activemq.broker-url=tcp://localhost:61616 spring.jms.pub-sub-domain=false spring.jms.template.default-destination=example.queue ``` 在上面的配置中,我们指定了ActiveMQ的地址和端口号,以及默认的JMS目的地(即消息队列或主题)。 总之,JMS Connection Factory是JMS规范中的概念,用于创建JMS连接。在使用ActiveMQ时,我们可以使用ActiveMQ提供的ActiveMQConnectionFactory来创建JMS Connection Factory。在Spring JMS框架中,我们可以使用Spring提供的ConnectionFactory来创建JMS Connection Factory,也可以使用其他第方提供的JMS Connection Factory。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值