在不使用ejb的情况下,怎么在jboss中简单地实现异步消息的发送和接收呢?
我们可以通过spring对jms的封装来实现。
首先,在jboss配置好你的ConnectionFactory, Queue
jms-ds.xml
<connection-factories> <tx-connection-factory> <jndi-name>TestConnectionFactory</jndi-name> <use-java-context>false</use-java-context> <xa-transaction/> <rar-name>jms-ra.rar</rar-name> <connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition> <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Queue</config-property> <config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property> <max-pool-size>20</max-pool-size> <security-domain-and-application>JmsXARealm</security-domain-and-application> </tx-connection-factory> </connection-factories>
jms-destination.xml
<mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=TestQueue"> <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> </mbean>
以上配置好后,就可以对此队列进行异步的消息接收、发送了。
利用spring进行消息的异步接收
在spring配置配置如下bean
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory"> <bean class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>TestConnectionFactory</value> </property> </bean> </property> <property name="destination"> <bean class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>queue/TestQueue</value> </property> </bean> </property> <property name="messageListener"> <bean class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <property name="delegate"> <bean class="com.test.message.ObjectMessageListener"/> </property> </bean> </property> </bean>
ObjectMessageListener的实现
public class ObjectMessageListener { public void handleMessage(Object obj) { //消费obj } }
至此,就可以实现消息的异步消费。
几个疑问:
1、大家可能对ObjectMessageListener 这个Listener的写法有的奇怪,一般情况下的Listener都需要继承jms里的MessageListener,而这里却没有,为什么呢?
这个要归功于spring的MessageListenerAdapter,它实现了我们的业务代码与jms的解耦,有兴趣的可以继续看看它的源码。
2、MessageListenerContainer有3个实现(SimpleMessageListenerContainer, DefaultMessageListenerContainer, ServerSessionMessageListenerContainer),这里为什么使用DefaultMessageListenerContainer,而不是SimpleMessageListenerContainer(spring guide里推荐使用它)
因为SimpleMessageListenerContainer里,有调用connection.setExceptionListener,jboss提供的jms实现不支持。
3、DefaultMessageListenerContainer提供了多线程并发消费的功能,但默认的concurrentConsumers=1,能否把它设置的大点呢?
在jboss中,一个connection只能生成一个session, 因此,这能把concurrentConsumers设置成1.
利用spring进行消息的异步发送
这个有很多文章介绍了,这里就不多述了。