posts - 33,  comments - 70,  trackbacks - 0

           

          說明: 本文并非基礎說明文章,如無基礎,請先參閱:
          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 -->
              
          <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
                  
          <property name="connectionFactory">
                      
          <!--  lets wrap in a pool to avoid creating a connection per send -->
                      
          <bean class="org.springframework.jms.connection.SingleConnectionFactory">
                          
          <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
                      
          </bean>
                  
          </property>
                  
          <!-- custom MessageConverter -->
                  
          <property name="messageConverter" ref="orderMessageConverter"/>
              
          </bean>
          <!--  OrderMessage converter  -->
              
          <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">
                  
          <property name="connectionFactory">
                      
          <!--  lets wrap in a pool to avoid creating a connection per send -->
                      
          <bean class="org.springframework.jms.connection.SingleConnectionFactory">
                          
          <property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
                      
          </bean>
                  
          </property>
                  
          <property name="messageConverter" ref="messageConverter"/>
              
          </bean>

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

           

          通過通用的CoverterHolder分發messageConverter實現,可以為多個pojo提供MessageConverter,并且有默認的messageConverter實現,并且可以通過 set Map<String, MessageConverter> converters 注入,提供特殊的pojoMessageConverter的實現,為真正項目中應用提供必要的支持。


          com.service.CoverterHolder 代碼為:

          public class CoverterHolder implements MessageConverter {
              
          private MessageConverter defaultMessageConverter;
              
          private Map<String, MessageConverter> converters = new HashMap<String, MessageConverter>();
              
              
              
          public Message toMessage(Object obj, Session session) throws JMSException {
                  String clz 
          = obj.getClass().getName();
                  
          if(converters.containsKey(clz)){
                      Message message 
          = converters.get(clz).toMessage(obj, session);
                      message.setObjectProperty(
          "meta-class", clz);
                      
          return message;
                  }
          else{
                      Message message
          =defaultMessageConverter.toMessage(obj,session);
                      message.setObjectProperty(
          "default-meta-class", clz);
                      
          return message;
                  }

              }


              
              
          public Object fromMessage(Message msg) throws JMSException {
                  
          if(msg.getObjectProperty("meta-class"!= null){
                      String clz
          = msg.getObjectProperty("meta-class").toString();
                      
          if(converters.containsKey(clz)){
                          
          return converters.get(clz).fromMessage(msg);
                      }

                  }
          else if(msg.getObjectProperty("default-meta-class"!= null){
                      
          return defaultMessageConverter.fromMessage(msg);
                  }
          else{
                      
          throw new JMSException("Msg:[" + msg + "] is not Map");
                  }

                  
                  
          return null;
              }


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


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


          }



          二.為大部分MessageConverter實現自己的默認功能

          DefaultMessageConverter 為默認的MessageConverter實現,擺脫重復繁瑣的MessageConverter AG and AG,懶人的福音。哈哈

          如果沒有特殊的要求,DefaultMessageConverter足以滿足90%以上的要求

          DefaultMessageConverter代碼:

          public class DefaultMessageConverter implements MessageConverter {
              
          public Message toMessage(Object obj, Session session) throws JMSException {
                  
          // check Type
                  ActiveMQObjectMessage objMsg = (ActiveMQObjectMessage) session
                          .createObjectMessage();
                  HashMap
          <String, byte[]> map = new HashMap<String, byte[]>();
                  
          try {
                      
          // POJO must implements Seralizable
                      ByteArrayOutputStream bos = new ByteArrayOutputStream();
                      ObjectOutputStream oos 
          = new ObjectOutputStream(bos);
                      oos.writeObject(obj);
                      map.put(
          "POJO", bos.toByteArray());
                      objMsg.setObjectProperty(
          "Map", map);

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

                  
          return objMsg;
              }


              
          public Object fromMessage(Message msg) throws JMSException {
                  
          if (msg instanceof ObjectMessage) {
                      HashMap
          <String, byte[]> map= (HashMap<String, byte[]>) ((ObjectMessage) msg).getObjectProperty("Map");
                       
          try {
                           
          //POJO must implements Seralizable
                           ByteArrayInputStream bis=new ByteArrayInputStream(map.get("POJO"));
                           ObjectInputStream ois
          =new ObjectInputStream(bis);
                           
          return ois.readObject();
                       }
           catch (IOException e) {
                          e.printStackTrace();
                      }
           catch (ClassNotFoundException e) {
                          e.printStackTrace();
                      }

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

              }



          在Spring中配置

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

          messageConverter 入住默認的MessageConverter實現。


          三.為特殊的MessageConverter實現提供自己的選擇

          例如 ReportPerdayMessageConverter為特殊的 POJO Coverter

          ReportPerdayMessageConverter代碼:

          public class ReportPerdayMessageConverter implements MessageConverter {
              
          public Message toMessage(Object obj, Session session) throws JMSException {
                  
          //
              }

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

          }

          com.domain.ReportPerday模型中注入特殊的自己消息轉換

          <!--  Holder Message converter  -->
              
          <bean id="messageConverter" class="com.service.CoverterHolder">
                  
          <!-- 擴展自己實現 converter -->        
                  
          <property name="converters">
                      
          <map>
                          
          <entry key="com.domain.ReportPerday">
                              
          <bean id="reportPerdayMessageConverter" class="com.service.ReportPerdayMessageConverter"/>                    
                          
          </entry>                
                      
          </map>
                  
          </property>    
                  
          <property name="defaultMessageConverter">
                      
          <bean class="com.service.DefaultMessageConverter"/>
                  
          </property>
              
          </bean>

          四.Message Driven POJO (MDP) 擴展Adapter

          解決對多個消費者 MDP的分發 

          ss中配置

          <!--  Message Driven POJO (MDP) -->
              
          <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
                  
          <constructor-arg>
                      
          <bean class="org.springside.bookstore.components.activemq.OrderMessageConsumer">
                          
          <property name="mailService" ref="mailService"/>
                      
          </bean>
                  
          </constructor-arg>
                  
          <!--  may be other method -->
                  
          <property name="defaultListenerMethod" value="sendEmail"/>
                  
          <!-- custom MessageConverter define -->
                  
          <property name="messageConverter" ref="orderMessageConverter"/>
              
          </bean> 

          明顯感覺<constructor-arg>中對于多個消費者不實用的特性。

           

          自己擴展

          <!--  Message Driven POJO (MDP) -->
              
          <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
                  
          <!--  may be other method -->
                  
          <constructor-arg>
                      
          <bean class="com.service.MessageConsumerAdapter" >
                          
          <property name="reportPerdayMessageConsumer" ref="reportPerdayMessageConsumer"/>
                      
          </bean>        
                  
          </constructor-arg>
                  
          <!--  may be other method -->
                  
          <property name="defaultListenerMethod" value="receive"/>
                  
          <!-- custom MessageConverter define -->
                  
          <property name="messageConverter" ref="messageConverter"/>
              
          </bean>

          MessageConsumerAdapter代碼
          public class MessageConsumerAdapter {
              
          private ReportPerdayMessageConsumer reportPerdayMessageConsumer;
              
              
          public void receive(Object obj) {
                  
          if (obj instanceof ReportPerday) {
                      System.out.println((ReportPerday)obj);
                  }
           else if (obj instanceof ReportPerday2) {
                      System.out.println((ReportPerday2)obj);
                  }

              }


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

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


              
          public void setReportPerdayMessageConsumer(
                      ReportPerdayMessageConsumer reportPerdayMessageConsumer) 
          {
                  
          this.reportPerdayMessageConsumer = reportPerdayMessageConsumer;
              }

          }


          MessageConsumerAdapter中可以入住多個要分發的消費者或者業務方法,根據POJO對象不通而選擇自己的消費者類型。 

           

           

          后話: http://wiki.springside.org.cn ActiveMQ 實用已經比較細致的入門講解和展示。再次重申,如果沒基礎,請閱讀ss中的文檔。

          本文目的只在搭建更為實用的JMS基礎設施,如有不明之處,共同討論與學習 :)

          文中代碼如下
          http://www.aygfsteel.com/Files/hellboys/activemq-example-nojar.zip


          posted on 2007-04-01 21:56 地獄男爵(hellboys) 閱讀(3324) 評論(0)  編輯  收藏 所屬分類: 編程語言(c/c++ java python sql ......)
          <2007年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          隨筆分類

          隨筆檔案

          文章檔案

          相冊

          連接

          最新隨筆

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 绥棱县| 满洲里市| 正镶白旗| 桂林市| 巴楚县| 凌云县| 蓝山县| 澄江县| 南丹县| 略阳县| 铜川市| 乌拉特后旗| 贡嘎县| 乳源| 黄龙县| 金昌市| 紫金县| 云南省| 宜兰市| 五家渠市| 紫阳县| 荆门市| 如皋市| 静安区| 秦皇岛市| 加查县| 衡阳市| 扶余县| 皋兰县| 荣成市| 平遥县| 内江市| 维西| 休宁县| 错那县| 克拉玛依市| 和平县| 溆浦县| 甘孜县| 蒙山县| 新源县|