博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring整合Jms学习(三)_MessageConverter介绍
阅读量:6470 次
发布时间:2019-06-23

本文共 12702 字,大约阅读时间需要 42 分钟。

1.4     消息转换器MessageConverter

MessageConverter的作用主要有双方面,一方面它能够把我们的非标准化Message对象转换成我们的目标Message对象,这主要是用在发送消息的时候;还有一方面它又能够把我们的Message对象转换成相应的目标对象,这主要是用在接收消息的时候。

以下我们就拿发送一个对象消息来举例,如果我们有这样一个需求:我们平台有一个发送邮件的功能,进行发送的时候我们仅仅是把我们的相关信息封装成一个JMS消息,然后利用JMS进行发送,在相应的消息监听器进行接收到的消息处理时才真正的进行消息发送。

如果我们有这么一个Email对象:

public class Email implements Serializable {     private static final long serialVersionUID = -658250125732806493L;     private String receiver;    private String title;    private String content;     public Email(String receiver, String title, String content) {        this.receiver = receiver;        this.title = title;        this.content = content;    }     public String getReceiver() {        return receiver;    }     public void setReceiver(String receiver) {        this.receiver = receiver;    }     public String getTitle() {        return title;    }     public void setTitle(String title) {        this.title = title;    }     public String getContent() {        return content;    }     public void setContent(String content) {        this.content = content;    }     @Override    public String toString() {        StringBuilder builder = new StringBuilder();        builder.append("Email [receiver=").append(receiver).append(", title=")                .append(title).append(", content=").append(content).append("]");        return builder.toString();    }    }

这个
Email
对象包括了一个简单的接收者
email
地址、邮件主题和邮件内容。我们在发送的时候就把这个对象封装成一个
ObjectMessage
进行发送。代码例如以下所看到的:

public class ProducerServiceImpl implements ProducerService {     @Autowired    private JmsTemplate jmsTemplate;        public void sendMessage(Destination destination, final Serializable obj) {        jmsTemplate.send(destination, new MessageCreator() {             public Message createMessage(Session session) throws JMSException {                ObjectMessage objMessage = session.createObjectMessage(obj);                return objMessage;            }                    });    } }

   这是相应的在没有使用MessageConverter的时候我们须要new一个MessageCreator接口对象,然后在其抽象方法createMessage内部使用session创建一个相应的消息。

在使用了MessageConverter的时候我们在使用JmsTemplate进行消息发送时仅仅须要调用其相应的convertAndSend方法就可以。

如:

 

public void sendMessage(Destination destination, final Serializable obj) {        //未使用MessageConverter的情况        /*jmsTemplate.send(destination, new MessageCreator() {             public Message createMessage(Session session) throws JMSException {                ObjectMessage objMessage = session.createObjectMessage(obj);                return objMessage;            }                    });*/        //使用MessageConverter的情况        jmsTemplate.convertAndSend(destination, obj);    }

这样JmsTemplate就会在其内部调用预定的MessageConverter对我们的消息对象进行转换。然后再进行发送。

       这个时候我们就须要定义我们的MessageConverter了。

要定义自己的MessageConverter非常easy。仅仅须要实现Spring为我们提供的MessageConverter接口就可以。我们先来看一下MessageConverter接口的定义:

public interface MessageConverter {     Message toMessage(Object object, Session session) throws JMSException, MessageConversionException;     Object fromMessage(Message message) throws JMSException, MessageConversionException; }

     
我们能够看到当中一共定义了两个方法
fromMessage
toMessage
fromMessage
是用来把一个
JMS Message
转换成相应的
Java
对象,而
toMessage
方法是用来把一个
Java
对象转换成相应的
JMS Message
。由于我们已经知道上面要发送的对象就是一个
Email
对象。所以在这里我们就简单地定义一个
EmailMessageConverter
用来把
Email
对象和相应的
ObjectMessage
进行转换,其代码例如以下:


import javax.jms.JMSException;import javax.jms.Message;import javax.jms.ObjectMessage;import javax.jms.Session; import org.springframework.jms.support.converter.MessageConversionException;import org.springframework.jms.support.converter.MessageConverter; public class EmailMessageConverter implements MessageConverter {     public Message toMessage(Object object, Session session)            throws JMSException, MessageConversionException {        return session.createObjectMessage((Serializable) object);    }     public Object fromMessage(Message message) throws JMSException,            MessageConversionException {        ObjectMessage objMessage = (ObjectMessage) message;        return objMessage.getObject();    } }

   这样当我们利用JmsTemplate的convertAndSend方法发送一个Email对象的时候就会把相应的Email对象当做參数调用我们定义好的EmailMessageConverter的toMessage方法。

       定义好我们的EmailMessageConverter之后就须要指定我们用来发送Email对象的JmsTemplate对象的messageConverter为EmailMessageConverter。这里我们在Spring的配置文件里定义JmsTemplate bean的时候就指定:

  
到此我们的
MessageConverter
就定义好了。也可以进行使用了,接着我们来进行測试一下,定义測试代码例如以下所看到的:
@Test    public void testObjectMessage() {        Email email = new Email("zhangsan@xxx.com", "主题", "内容");        producerService.sendMessage(destination, email);    }

       
上面
destination
相应的接收处理的
MessageListener
方法例如以下所看到的:

public class ConsumerMessageListener implements MessageListener {     public void onMessage(Message message) {                if (message instanceof ObjectMessage) {            ObjectMessage objMessage = (ObjectMessage) message;            try {                Object obj = objMessage.getObject();                Email email = (Email) obj;                System.out.println("接收到一个ObjectMessage,包括Email对象。

"); System.out.println(email); } catch (JMSException e) { e.printStackTrace(); } } } }


     
之前说了
MessageConverter
有双方面的功能,除了把
Java
对象转换成相应的
Jms Message
之外还能够把
Jms Message
转换成相应的
Java
对象。我们看上面的消息监听器在接收消息的时候接收到的就是一个
Jms Message
,假设我们要利用
MessageConverter
来把它转换成相应的
Java
对象的话。仅仅能是我们往里面注入一个相应的
MessageConverter
,然后在里面手动的调用。如:


public class ConsumerMessageListener implements MessageListener {     private MessageConverter messageConverter;        public void onMessage(Message message) {                if (message instanceof ObjectMessage) {            ObjectMessage objMessage = (ObjectMessage) message;            try {                /*Object obj = objMessage.getObject();                Email email = (Email) obj;*/                Email email = (Email) messageConverter.fromMessage(objMessage);                System.out.println("接收到一个ObjectMessage,包括Email对象。

"); System.out.println(email); } catch (JMSException e) { e.printStackTrace(); } } } public MessageConverter getMessageConverter() { return messageConverter; } public void setMessageConverter(MessageConverter messageConverter) { this.messageConverter = messageConverter; } }


    当我们使用MessageListenerAdapter来作为消息监听器的时候,我们能够为它指定一个相应的MessageConverter,这样Spring在处理接收到的消息的时候就会自己主动地利用我们指定的MessageConverter对它进行转换,然后把转换后的Java对象作为參数调用指定的消息处理方法。这里我们再把前面解说MessageListenerAdapter时定义的MessageListenerAdapter拿来做一个測试,我们指定它的MessageConverter为我们定义好的EmailMessageConverter。

 


    
然后在我们的真正用于处理接收到的消息的
ConsumerListener
中加入一个
receiveMessage
方法。加入后其代码例如以下所看到的:

public class ConsumerListener {     public void receiveMessage(String message) {        System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message);    }        public void receiveMessage(Email email) {        System.out.println("接收到一个包括Email的ObjectMessage。");        System.out.println(email);    }    }
   
然后我们定义例如以下測试代码:

@Test    public void testObjectMessage() {        Email email = new Email("zhangsan@xxx.com", "主题", "内容");        producerService.sendMessage(adapterQueue, email);    }

       由于我们给MessageListenerAdapter指定了一个MessageConverter,并且是一个EmailMessageConverter,所以当MessageListenerAdapter接收到一个消息后。它会调用我们指定的MessageConverter的fromMessage方法把它转换成一个Java对象。依据定义这里会转换成一个Email对象。然后会把这个Email对象作为參数调用我们通过defaultListenerMethod属性指定的默认处理器方法,依据定义这里就是receiveMessage方法,可是我们能够看到在ConsumerListener中我们一共定义了两个receiveMessage方法,由于是通过转换后的Email对象作为參数进行方法调用的,所以这里调用的就应该是參数类型为Email的receiveMessage方法了。上述測试代码执行后会输出例如以下结果:

        讲到这里可能有读者就会有疑问了,说我们在之前解说MessageListenerAdapter的时候不是没有指定相应的MessageConverter,然后发送了一个TextMessage,结果Spring还是把它转换成一个String对象,调用了ConsumerListener參数类型为String的receiveMessage方法吗?那你这个MessageConverter在MessageListenerAdapter进行消息接收的时候也没什么用啊。

       事实上还是实用的。在我们使用MessageListenerAdapter时,在对其进行初始化也就是调用其构造方法时。它会默认new一个Spring已经为我们实现了的MessageConverter——SimpleMessageConverter作为其默认的MessageConverter,这也就是为什么我们在使用MessageListenerAdapter的时候不须要指定MessageConverter可是消息还是会转换成相应的Java对象的原因。所以默认情况下我们使用MessageListenerAdapter时其相应的MessageListener的处理器方法參数类型必须是一个普通Java对象,而不能是相应的Jms Message对象。

       那假设我们在处理Jms Message的时候想使用MessageListenerAdapter,然后又希望处理最原始的Message,而不是经过MessageConverter进行转换后的Message该怎么办呢?这个时候我们仅仅须要在定义MessageListenerAdapter的时候指定其MessageConverter为空就能够了。


    
那么这个时候我们的真实
MessageListener
的处理器方法參数类型就应该是
Jms Message
或相应的
Jms Message
子类型了,不然就会调用不到相应的处理方法了。这里由于我们发送的是一个
ObjectMessage
。所以这里就加入一个相应的參数类型为
ObjectMessage
receiveMessage
方法了。

public void receiveMessage(ObjectMessage message) throws JMSException {        System.out.println(message.getObject());    }

     刚刚讲到Spring已经为我们实现了一个简单的MessageConverter。即org.springframework.jms.support.converter.SimpleMessageConverter,事实上Spring在初始化JmsTemplate的时候也指定了其相应的MessageConverter为一个SimpleMessageConverter,所以假设我们寻常没有什么特殊要求的时候能够直接使用JmsTemplate的convertAndSend系列方法进行消息发送。而不必繁琐的在调用send方法时自己new一个MessageCreator进行相应Message的创建。

这里我们也来看一下SimpleMessageConverter的定义,假设认为它不能满足你的要求,那我们能够对它里面的部分方法进行重写,或者是全然实现自己的MessageConverter。

public class SimpleMessageConverter implements MessageConverter {     public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {        if (object instanceof Message) {            return (Message) object;        }        else if (object instanceof String) {            return createMessageForString((String) object, session);        }        else if (object instanceof byte[]) {            return createMessageForByteArray((byte[]) object, session);        }        else if (object instanceof Map) {            return createMessageForMap((Map) object, session);        }        else if (object instanceof Serializable) {            return createMessageForSerializable(((Serializable) object), session);        }        else {            throw new MessageConversionException("Cannot convert object of type [" +                    ObjectUtils.nullSafeClassName(object) + "] to JMS message. Supported message " +                    "payloads are: String, byte array, Map
, Serializable object."); } } public Object fromMessage(Message message) throws JMSException, MessageConversionException { if (message instanceof TextMessage) { return extractStringFromMessage((TextMessage) message); } else if (message instanceof BytesMessage) { return extractByteArrayFromMessage((BytesMessage) message); } else if (message instanceof MapMessage) { return extractMapFromMessage((MapMessage) message); } else if (message instanceof ObjectMessage) { return extractSerializableFromMessage((ObjectMessage) message); } else { return message; } } protected TextMessage createMessageForString(String text, Session session) throws JMSException { return session.createTextMessage(text); } protected BytesMessage createMessageForByteArray(byte[] bytes, Session session) throws JMSException { BytesMessage message = session.createBytesMessage(); message.writeBytes(bytes); return message; } protected MapMessage createMessageForMap(Map

> map, Session session) throws JMSException { MapMessage message = session.createMapMessage(); for (Map.Entry entry : map.entrySet()) { if (!(entry.getKey() instanceof String)) { throw new MessageConversionException("Cannot convert non-String key of type [" + ObjectUtils.nullSafeClassName(entry.getKey()) + "] to JMS MapMessage entry"); } message.setObject((String) entry.getKey(), entry.getValue()); } return message; } protected ObjectMessage createMessageForSerializable(Serializable object, Session session) throws JMSException { return session.createObjectMessage(object); } protected String extractStringFromMessage(TextMessage message) throws JMSException { return message.getText(); } protected byte[] extractByteArrayFromMessage(BytesMessage message) throws JMSException { byte[] bytes = new byte[(int) message.getBodyLength()]; message.readBytes(bytes); return bytes; } protected Map extractMapFromMessage(MapMessage message) throws JMSException { Map<String, Object> map = new HashMap<String, Object>(); Enumeration en = message.getMapNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); map.put(key, message.getObject(key)); } return map; } protected Serializable extractSerializableFromMessage(ObjectMessage message) throws JMSException { return message.getObject(); } }





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5086334.html,如需转载请自行联系原作者

你可能感兴趣的文章
[LeetCode] Minimum Depth of Binary Tree
查看>>
,net运行框架
查看>>
Java 中 Emoji 的正则表达式
查看>>
Mixin Network第一届开发者大赛作品介绍- dodice, diceos和Fox.one luckycoin
查看>>
安卓Glide(4.7.1)使用笔记 01 - 引入项目
查看>>
AndroidNote
查看>>
中金易云:为出版社找到下一本《解忧杂货店》
查看>>
Flex布局
查看>>
Material Design之 AppbarLayout 开发实践总结
查看>>
Android中的SurfaceView详解
查看>>
Flutter之MaterialApp使用详解
查看>>
DataBinding最全使用说明
查看>>
原生Js交互之DSBridge
查看>>
Matlab编程之——卷积神经网络CNN代码解析
查看>>
白洋淀周末游
查看>>
三篇文章了解 TiDB 技术内幕 —— 说计算
查看>>
copy strong weak assign的区别
查看>>
OpenCV 入门
查看>>
css 3D transform变换
查看>>
ele表格合并行之后的selection选中
查看>>