JMS--ActiveMq与spring整合(二)
原文地址:http://blog.csdn.net/haoxingfeng/article/details/9167895
在我們和Spring 整合的時候,對于消費者而言我們有三種不同類型的監聽器可以去選擇,他們分別是MessageListener,SessionAwareMessageListener,MessageListenerAdapter,下面我們就來說說他們之間的區別。
1、MessageListener
MessageListener是最原始的消息監聽器,是JMS規范中定義的接口。其中定義了用于處理消息的onMessage(Message message) 接口,改方法只接受一個Message類型的參數,在JMS--ActiveMq與spring整合(一)種我們使用的就是MessageListener。
2、SessionAwareMessageListener
SessionAwareMessageListener 并不是原始的消息監聽器。它是Spring為我們提供的,它不是標準的JMS MessageListener。原始的MessageListener只是純粹的用來接收消息,假如我們在使用MessageListener處理接收到的消息時我們需要發送一個消息通知對方我們已經收到這個消息了,那么這個時候我們就需要在代碼里面去重新獲取一個Connection或Session。SessionAwareMessageListener的設計就是為了方便我們在接收到消息后發送一個回復的消息,它同樣為我們提供了一個處理接收到的消息的onMessage方法,但是這個方法可以同時接收兩個參數,一個是表示當前接收到的消息Message,另一個就是可以用來發送消息的Session對象。
xml配置:
<bean id="sessionAwareQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>sessionAwareQueue</value>
</constructor-arg>
</bean>
<bean id="sessionAwareConsumerMessageListener" class="com.ghq.activemq.SessionAwareConsumer">
<property name="destination" ref="queue"></property>
</bean>
<bean id="sessionAwareMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="destination" ref="sessionAwareQueue"></property>
<property name="messageListener" ref="sessionAwareConsumerMessageListener"></property>
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
Java代碼:
public class SessionAwareConsumer implements SessionAwareMessageListener<Message> {
private Destination destination;
public void onMessage(Message message, Session session) throws JMSException {
TextMessage tMessage = (TextMessage) message;
System.out.println("SessionAwareConsumer接收消息:"+tMessage.getText());
MessageProducer producer = session.createProducer(destination);
producer.send(session.createTextMessage(tMessage.getText()));
}
public Destination getDestination() {
return destination;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
}
producer發送了一個消息到sessionAwareQueue ,sessionAwareMessageListenerContainer接收消息將消息傳遞給真正的處理這SessionAwareConsumer,SessionAwareConsumer出來了消息并向queue 輸出了改消息,并向queue發送了改消息。messageListenerContainer 處理了改消息。
3、MessageListenerAdapter
MessageListenerAdapter實現了SessionAwareMessageListener和MessageListener接口。它的主要作用是將接收到的消息進行類型轉換
然后通過反射的形式把它交給一個普通的Java類進行處理。
?????? MessageListenerAdapter會把接收到的消息做如下轉換:
?????? TextMessage轉換為String對象;
?????? BytesMessage轉換為byte數組;
?????? MapMessage轉換為Map對象;
?????? ObjectMessage轉換為對應的Serializable對象。
?既然前面說了MessageListenerAdapter會把接收到的消息做一個類型轉換,然后利用反射把它交給真正的目標處理器——一個普通的Java類進行處理(如果真正的目標處理器是一個MessageListener或者是一個SessionAwareMessageListener,那么Spring將直接使用接收到的Message對象作為參數調用它們的onMessage方法,而不會再利用反射去進行調用),那么我們在定義一個MessageListenerAdapter的時候就需要為它指定這樣一個目標類。這個目標類我們可以通過MessageListenerAdapter的構造方法參數指定,如:
?<bean?id="messageListenerAdapter"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">?
? <constructor-arg><bean?class="com.ghq.activemq.Consumer"/></constructor-arg>
</bean>
?也可以通過它的delegate屬性來指定,如:
xml:
<bean id="adapterQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>adapterQueue</value>
</constructor-arg>
</bean>
<bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<property name="delegate">
<bean class="com.ghq.activemq.AdapterRealClass"></bean>
</property>
<!-- 默認調用 com.ghq.activemq.AdapterRealClass 類的handleMessage方法,也可以通過defaultListenerMethod 屬性來設置方法名字-->
<!-- <property name="defaultListenerMethod" value="myhandleMessage"></property> -->
</bean>
<bean id="adapterMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="destination" ref="adapterQueue"></property>
<property name="messageListener" ref="messageListenerAdapter"></property>
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
MessageListenerAdapter除了會自動的把一個普通Java類當做MessageListener來處理接收到的消息之外,其另外一個主要的功能是可以自動的發送返回消息。
???? 當我們用于處理接收到的消息的方法的返回值不為空的時候,Spring會自動將它封裝為一個JMS Message,然后自動進行回復。那么這個時候這個回復消息將發送到哪里呢?這主要有兩種方式可以指定。
???????第一,可以通過發送的Message的setJMSReplyTo方法指定該消息對應的回復消息的目的地。這里我們把我們的生產者發送消息的代碼做一下修改,在發送消息之前先指定該消息對應的回復目的地為一個叫responseQueue的隊列目的地,具體代碼如下所示:
在發送這代碼中加入下面一行話:
TextMessage tMessage = session.createTextMessage(message);
tMessage.setJMSReplyTo(responseQueue);
xml配置(去掉上面調用默認方法handleMessage的注釋,調用我們自己的myhandleMessage):
<bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>responseQueue</value>
</constructor-arg>
</bean>
<bean id="responseQueueListener" class="com.ghq.activemq.ResponseQueueListener" />
<bean id="adapterMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="destination" ref="responseQueue"></property>
<property name="messageListener" ref="responseQueueListener"></property>
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
簡單java類:
public class AdapterRealClass {
public void handleMessage(String message){
System.out.println("AdapterRealClass handleMessage():"+message);
}
public String myhandleMessage(String message){
System.out.println("AdapterRealClass myhandleMessage():"+message);
return "myhandleMessage"+message;
}
}
?第二,通過MessageListenerAdapter的defaultResponseDestination屬性來指定。這里我們也來做一個測試,首先維持生產者發送消息的代碼不變,即發送消息前不通過Message的setJMSReplyTo方法指定消息的回復目的地。
既然我們可以通過兩種方式來指定MessageListenerAdapter自動發送回復消息的目的地,那么當我們兩種方式都指定了而且它們的目的地還不一樣的時候會怎么發送呢?當兩種方式都指定了消息的回復目的地的時候使用發送消息的setJMSReplyTo方法指定的目的地將具有較高的優先級,MessageListenerAdapter將只往該方法指定的消息回復目的地發送回復消息。
轉載于:https://www.cnblogs.com/gaohuiqian/p/5220235.html
總結
以上是生活随笔為你收集整理的JMS--ActiveMq与spring整合(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vmware下linux虚拟机传文件解决
- 下一篇: 机房重构 之 抽象工厂+反射+配置文件