说明: 本文并非基础说明文章,如无基础,请先参阅:
1. http://wiki.springside.org.cn/display/springside/ActiveMQ
2. http://wiki.springside.org.cn/display/springside/ActiveMQ-part2
仅以springside-2.0-RC1版本扩展
由于为每个POJO类实现自己的MessageConverter ,所以配置xml和使用比较繁琐。
一.MessageConverter 扩展 
在springside-2.0-RC1版本中
 <!--  Spring JmsTemplate config -->
<!--  Spring JmsTemplate config -->
 <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
 <property name="connectionFactory">
        <property name="connectionFactory">
 <!--  lets wrap in a pool to avoid creating a connection per send -->
            <!--  lets wrap in a pool to avoid creating a connection per send -->
 <bean class="org.springframework.jms.connection.SingleConnectionFactory">
            <bean class="org.springframework.jms.connection.SingleConnectionFactory">
 <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
                <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
 </bean>
            </bean>
 </property>
        </property>
 <!-- custom MessageConverter -->
        <!-- custom MessageConverter -->
 <property name="messageConverter" ref="orderMessageConverter"/>
        <property name="messageConverter" ref="orderMessageConverter"/>
 </bean>
    </bean>
 <!--  OrderMessage converter  -->
<!--  OrderMessage converter  -->
 <bean id="orderMessageConverter" class="org.springside.bookstore.components.activemq.OrderMessageConverter"/>
    <bean id="orderMessageConverter" class="org.springside.bookstore.components.activemq.OrderMessageConverter"/>

orderMessageConverter为 MessageConverter实现类。
但是如果在实际项目中应用的话,如果为2个或2个以上的pojo 实现MessageConverter的话,那么就会发现jmsTemplate让人比较尴尬的位置,启动的注入messageConverter也不是,动态messageConverter也不是, 显的不是那么平易近人了。
 
自己的扩展
 <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
 <property name="connectionFactory">
        <property name="connectionFactory">
 <!--  lets wrap in a pool to avoid creating a connection per send -->
            <!--  lets wrap in a pool to avoid creating a connection per send -->
 <bean class="org.springframework.jms.connection.SingleConnectionFactory">
            <bean class="org.springframework.jms.connection.SingleConnectionFactory">
 <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
                <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
 </bean>
            </bean>
 </property>
        </property>
 <property name="messageConverter" ref="messageConverter"/>
        <property name="messageConverter" ref="messageConverter"/>
 </bean>
    </bean>

 <!--  Holder Message converter  -->
<!--  Holder Message converter  -->
 <bean id="messageConverter" class="com.service.CoverterHolder" />
    <bean id="messageConverter" class="com.service.CoverterHolder" />

 
通过通用的CoverterHolder分发messageConverter实现,可以为多个pojo提供MessageConverter,并且有默认的messageConverter实现,并且可以通过 set Map<String, MessageConverter> converters 注入,提供特殊的pojo的MessageConverter的实现,为真正项目中应用提供必要的支持。
com.service.CoverterHolder 代码为:

 public class CoverterHolder implements MessageConverter
public class CoverterHolder implements MessageConverter  {
{
 private MessageConverter defaultMessageConverter;
    private MessageConverter defaultMessageConverter;
 private Map<String, MessageConverter> converters = new HashMap<String, MessageConverter>();
    private Map<String, MessageConverter> converters = new HashMap<String, MessageConverter>();
 
    
 
    

 public Message toMessage(Object obj, Session session) throws JMSException
    public Message toMessage(Object obj, Session session) throws JMSException  {
{
 String clz = obj.getClass().getName();
        String clz = obj.getClass().getName();

 if(converters.containsKey(clz))
        if(converters.containsKey(clz)) {
{
 Message message = converters.get(clz).toMessage(obj, session);
            Message message = converters.get(clz).toMessage(obj, session);
 message.setObjectProperty("meta-class", clz);
            message.setObjectProperty("meta-class", clz);
 return message;
            return message;

 }else
        }else {
{
 Message message=defaultMessageConverter.toMessage(obj,session);
            Message message=defaultMessageConverter.toMessage(obj,session);
 message.setObjectProperty("default-meta-class", clz);
            message.setObjectProperty("default-meta-class", clz);
 return message;
            return message;
 }
        }
 }
    }

 
    

 public Object fromMessage(Message msg) throws JMSException
    public Object fromMessage(Message msg) throws JMSException  {
{

 if(msg.getObjectProperty("meta-class") != null)
        if(msg.getObjectProperty("meta-class") != null) {
{
 String clz= msg.getObjectProperty("meta-class").toString();
            String clz= msg.getObjectProperty("meta-class").toString();

 if(converters.containsKey(clz))
            if(converters.containsKey(clz)) {
{
 return converters.get(clz).fromMessage(msg);
                return converters.get(clz).fromMessage(msg);
 }
            }

 }else if(msg.getObjectProperty("default-meta-class") != null)
        }else if(msg.getObjectProperty("default-meta-class") != null) {
{
 return defaultMessageConverter.fromMessage(msg);
            return defaultMessageConverter.fromMessage(msg);

 }else
        }else {
{
 throw new JMSException("Msg:[" + msg + "] is not Map");
            throw new JMSException("Msg:[" + msg + "] is not Map");
 }
        }
 
        
 return null;
        return null;
 }
    }


 public void setConverters(Map<String, MessageConverter> converters)
    public void setConverters(Map<String, MessageConverter> converters)  {
{
 this.converters = converters;
        this.converters = converters;
 }
    }


 public void setDefaultMessageConverter(MessageConverter defaultMessageConverter)
    public void setDefaultMessageConverter(MessageConverter defaultMessageConverter)  {
{
 this.defaultMessageConverter = defaultMessageConverter;
        this.defaultMessageConverter = defaultMessageConverter;
 }
    }

 }
}

二.为大部分MessageConverter实现自己的默认功能 
DefaultMessageConverter 为默认的MessageConverter实现,摆脱重复繁琐的MessageConverter AG and AG,懒人的福音。哈哈
如果没有特殊的要求,DefaultMessageConverter足以满足90%以上的要求 。
DefaultMessageConverter代码:

 public class DefaultMessageConverter implements MessageConverter
public class DefaultMessageConverter implements MessageConverter  {
{

 public Message toMessage(Object obj, Session session) throws JMSException
    public Message toMessage(Object obj, Session session) throws JMSException  {
{
 // check Type
        // check Type
 ActiveMQObjectMessage objMsg = (ActiveMQObjectMessage) session
        ActiveMQObjectMessage objMsg = (ActiveMQObjectMessage) session
 .createObjectMessage();
                .createObjectMessage();
 HashMap<String, byte[]> map = new HashMap<String, byte[]>();
        HashMap<String, byte[]> map = new HashMap<String, byte[]>();

 try
        try  {
{
 // POJO must implements Seralizable
            // POJO must implements Seralizable
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(bos);
            ObjectOutputStream oos = new ObjectOutputStream(bos);
 oos.writeObject(obj);
            oos.writeObject(obj);
 map.put("POJO", bos.toByteArray());
            map.put("POJO", bos.toByteArray());
 objMsg.setObjectProperty("Map", map);
            objMsg.setObjectProperty("Map", map);


 } catch (IOException e)
        } catch (IOException e)  {
{
 e.printStackTrace();
            e.printStackTrace();            
 }
        }
 return objMsg;
        return objMsg;
 }
    }


 public Object fromMessage(Message msg) throws JMSException
    public Object fromMessage(Message msg) throws JMSException  {
{

 if (msg instanceof ObjectMessage)
        if (msg instanceof ObjectMessage)  {
{
 HashMap<String, byte[]> map= (HashMap<String, byte[]>) ((ObjectMessage) msg).getObjectProperty("Map");
            HashMap<String, byte[]> map= (HashMap<String, byte[]>) ((ObjectMessage) msg).getObjectProperty("Map");

 try
             try  {
{
 //POJO must implements Seralizable
                 //POJO must implements Seralizable
 ByteArrayInputStream bis=new ByteArrayInputStream(map.get("POJO"));
                 ByteArrayInputStream bis=new ByteArrayInputStream(map.get("POJO"));
 ObjectInputStream ois=new ObjectInputStream(bis);
                 ObjectInputStream ois=new ObjectInputStream(bis);
 return ois.readObject();
                 return ois.readObject();

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

 } catch (ClassNotFoundException e)
            } catch (ClassNotFoundException e)  {
{
 e.printStackTrace();
                e.printStackTrace();
 }
            }
 return null;
             return null;

 } else
        } else  {
{
 throw new JMSException("Msg:[" + msg + "] is not Map");
            throw new JMSException("Msg:[" + msg + "] is not Map");
 }
        }
 }
    }


在Spring中配置 
 <!--  Holder Message converter  -->
<!--  Holder Message converter  -->
 <bean id="messageConverter" class="com.service.CoverterHolder">
    <bean id="messageConverter" class="com.service.CoverterHolder">        
 <property name="defaultMessageConverter">
        <property name="defaultMessageConverter">
 <bean class="com.service.DefaultMessageConverter"/>
            <bean class="com.service.DefaultMessageConverter"/>
 </property>
        </property>
 </bean>
    </bean>

为 messageConverter 入住默认的MessageConverter实现。
三.为特殊的MessageConverter实现提供自己的选择
例如 ReportPerdayMessageConverter为特殊的 POJO Coverter。
ReportPerdayMessageConverter代码:

 public class ReportPerdayMessageConverter implements MessageConverter
public class ReportPerdayMessageConverter implements MessageConverter  {
{

 public Message toMessage(Object obj, Session session) throws JMSException
    public Message toMessage(Object obj, Session session) throws JMSException  {
{
 //…
        //…
 }
    }

 public Object fromMessage(Message msg) throws JMSException
    public Object fromMessage(Message msg) throws JMSException  {
{
 //…
        //…
 }
}
 }
}
在com.domain.ReportPerday模型中注入特殊的自己消息转换
 <!--  Holder Message converter  -->
<!--  Holder Message converter  -->
 <bean id="messageConverter" class="com.service.CoverterHolder">
    <bean id="messageConverter" class="com.service.CoverterHolder">
 <!-- 扩展自己实现 converter -->
        <!-- 扩展自己实现 converter -->        
 <property name="converters">
        <property name="converters">
 <map>
            <map>
 <entry key="com.domain.ReportPerday">
                <entry key="com.domain.ReportPerday">
 <bean id="reportPerdayMessageConverter" class="com.service.ReportPerdayMessageConverter"/>
                    <bean id="reportPerdayMessageConverter" class="com.service.ReportPerdayMessageConverter"/>                    
 </entry>
                </entry>                
 </map>
            </map>
 </property>
        </property>    
 <property name="defaultMessageConverter">
        <property name="defaultMessageConverter">
 <bean class="com.service.DefaultMessageConverter"/>
            <bean class="com.service.DefaultMessageConverter"/>
 </property>
        </property>
 </bean>
    </bean>四.
Message Driven POJO (MDP) 扩展Adapter
解决对多个消费者 MDP的分发 
ss中配置 
 <!--  Message Driven POJO (MDP) -->
<!--  Message Driven POJO (MDP) -->
 <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
 <constructor-arg>
        <constructor-arg>
 <bean class="org.springside.bookstore.components.activemq.OrderMessageConsumer">
            <bean class="org.springside.bookstore.components.activemq.OrderMessageConsumer">
 <property name="mailService" ref="mailService"/>
                <property name="mailService" ref="mailService"/>
 </bean>
            </bean>
 </constructor-arg>
        </constructor-arg>
 <!--  may be other method -->
        <!--  may be other method -->
 <property name="defaultListenerMethod" value="sendEmail"/>
        <property name="defaultListenerMethod" value="sendEmail"/>
 <!-- custom MessageConverter define -->
        <!-- custom MessageConverter define -->
 <property name="messageConverter" ref="orderMessageConverter"/>
        <property name="messageConverter" ref="orderMessageConverter"/>
 </bean>
    </bean> 明显感觉<constructor-arg>中对于多个消费者不实用的特性。
 
自己扩展
 <!--  Message Driven POJO (MDP) -->
<!--  Message Driven POJO (MDP) -->
 <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
 <!--  may be other method -->
        <!--  may be other method -->
 <constructor-arg>
        <constructor-arg>
 <bean class="com.service.MessageConsumerAdapter" >
            <bean class="com.service.MessageConsumerAdapter" >
 <property name="reportPerdayMessageConsumer" ref="reportPerdayMessageConsumer"/>
                <property name="reportPerdayMessageConsumer" ref="reportPerdayMessageConsumer"/>
 </bean>
            </bean>        
 </constructor-arg>
        </constructor-arg>
 <!--  may be other method -->
        <!--  may be other method -->
 <property name="defaultListenerMethod" value="receive"/>
        <property name="defaultListenerMethod" value="receive"/>
 <!-- custom MessageConverter define -->
        <!-- custom MessageConverter define -->
 <property name="messageConverter" ref="messageConverter"/>
        <property name="messageConverter" ref="messageConverter"/>
 </bean>
    </bean>

 public class MessageConsumerAdapter
public class MessageConsumerAdapter  {
{
 private ReportPerdayMessageConsumer reportPerdayMessageConsumer;
    private ReportPerdayMessageConsumer reportPerdayMessageConsumer;
 
    

 public void receive(Object obj)
    public void receive(Object obj)  {
{

 if (obj instanceof ReportPerday)
        if (obj instanceof ReportPerday)  {
{
 System.out.println((ReportPerday)obj);
            System.out.println((ReportPerday)obj);

 } else if (obj instanceof ReportPerday2)
        } else if (obj instanceof ReportPerday2)  {
{
 System.out.println((ReportPerday2)obj);
            System.out.println((ReportPerday2)obj);
 }
        }
 }
    }


 public void receive(ReportPerday reportPerday) throws Exception
    public void receive(ReportPerday reportPerday) throws Exception  {
{
 reportPerdayMessageConsumer.sendEmail(reportPerday);
        reportPerdayMessageConsumer.sendEmail(reportPerday);
 }
    }

 public void receive(ReportPerday2 reportPerday2) throws Exception
    public void receive(ReportPerday2 reportPerday2) throws Exception  {
{
 //do other service consumer
        //do other service consumer
 System.out.println("ReportPerday2 Bean do other service consumer ");
        System.out.println("ReportPerday2 Bean do other service consumer ");
 }
    }

 public void setReportPerdayMessageConsumer(
    public void setReportPerdayMessageConsumer(

 ReportPerdayMessageConsumer reportPerdayMessageConsumer)
            ReportPerdayMessageConsumer reportPerdayMessageConsumer)  {
{
 this.reportPerdayMessageConsumer = reportPerdayMessageConsumer;
        this.reportPerdayMessageConsumer = reportPerdayMessageConsumer;
 }
    }
 }
}
MessageConsumerAdapter中可以入住多个要分发的消费者或者业务方法,根据POJO对象不通而选择自己的消费者类型。 
 
 
后话: http://wiki.springside.org.cn 对ActiveMQ 实用已经比较细致的入门讲解和展示。再次重申,如果没基础,请阅读ss中的文档。
本文目的只在搭建更为实用的JMS基础设施,如有不明之处,共同讨论与学习 :)
文中代码如下
http://www.blogjava.net/Files/hellboys/activemq-example-nojar.zip