ActiveMQ4.1 +Spring2.0的POJO JMS方案 扩展,以更加实用(基于ss).二
一:续一,说明一的可使用性。
<
amq:queue
id
="destination.report"
physicalName
="active.jms.report"
/>
< amq:queue id ="destination.point" physicalName ="active.jms.point" />
< amq:queue id ="destination.point" physicalName ="active.jms.point" />
queue : 队列的名字 for 制造者.
感觉org.springframework.jms.listener.DefaultMessageListenerContainer 做的不好,如果destination property能做一个可包含多个队列,并且有选择性的messageListener就好了,这样就避免下面的监听的尴尬了。呵呵
<!--
listener container,MDP无需实现接口
-->
< bean id ="fluxPerhourListenerContainer" class ="org.springframework.jms.listener.DefaultMessageListenerContainer" >
< property name ="connectionFactory" ref ="jmsConnectionFactory" />
< property name ="destination" ref ="destination.fluxPerhour" />
< property name ="messageListener" ref ="messageListener" />
</ bean >
< bean id ="fluxPerDayListenerContainer" class ="org.springframework.jms.listener.DefaultMessageListenerContainer" >
< property name ="connectionFactory" ref ="jmsConnectionFactory" />
< property name ="destination" ref ="destination.fluxPerday" />
< property name ="messageListener" ref ="messageListener" />
</ bean >
< bean id ="reportPerdayProducer" class ="com.jms.ReportPerdayProducer" >
< property name ="template" ref ="jmsTemplate" />
< property name ="destination" ref ="destination.report" />
</ bean >
< bean id ="pointProducer" class ="com.jms.PointProducer" >
< property name ="template" ref ="jmsTemplate" />
< property name ="destination" ref ="destination.point" />
</ bean >
< bean id ="fluxPerhourListenerContainer" class ="org.springframework.jms.listener.DefaultMessageListenerContainer" >
< property name ="connectionFactory" ref ="jmsConnectionFactory" />
< property name ="destination" ref ="destination.fluxPerhour" />
< property name ="messageListener" ref ="messageListener" />
</ bean >
< bean id ="fluxPerDayListenerContainer" class ="org.springframework.jms.listener.DefaultMessageListenerContainer" >
< property name ="connectionFactory" ref ="jmsConnectionFactory" />
< property name ="destination" ref ="destination.fluxPerday" />
< property name ="messageListener" ref ="messageListener" />
</ bean >
< bean id ="reportPerdayProducer" class ="com.jms.ReportPerdayProducer" >
< property name ="template" ref ="jmsTemplate" />
< property name ="destination" ref ="destination.report" />
</ bean >
< bean id ="pointProducer" class ="com.jms.PointProducer" >
< property name ="template" ref ="jmsTemplate" />
< property name ="destination" ref ="destination.point" />
</ bean >
producer不能重用,因为send到不同destination,所有没办法重用。如果能对producer做一个默认统一的封装就好了. 但是DefaultProducer.那么应该注意队列线程安全方面,目前没有什么好的想法,就采用通用一些的办法,不过xml和代码稍多一些.
然后就用到 前面文章一 里面的内容了,非常简便。
<!--
Message Driven POJO (MDP)
-->
< bean id ="messageListener" class ="org.springframework.jms.listener.adapter.MessageListenerAdapter" >
<!-- may be other method -->
< constructor-arg >
< bean class ="com..jms.MessageConsumerAdapter" >
<!--业务接口/业务门面-->
< property name ="transfersManager" ref ="transfersManager" />
</ bean >
</ constructor-arg >
<!-- may be other method -->
< property name ="defaultListenerMethod" value ="receive" />
<!-- custom MessageConverter define -->
< property name ="messageConverter" ref ="messageConverter" />
</ bean >
<!--
Holder Message converter
-->
< bean id ="messageListener" class ="org.springframework.jms.listener.adapter.MessageListenerAdapter" >
<!-- may be other method -->
< constructor-arg >
< bean class ="com..jms.MessageConsumerAdapter" >
<!--业务接口/业务门面-->
< property name ="transfersManager" ref ="transfersManager" />
</ bean >
</ constructor-arg >
<!-- may be other method -->
< property name ="defaultListenerMethod" value ="receive" />
<!-- custom MessageConverter define -->
< property name ="messageConverter" ref ="messageConverter" />
</ bean >
< bean id ="messageConverter" class ="com.jms.CoverterHolder" >
< property name ="defaultMessageConverter" >
< bean class ="com.jms.DefaultMessageConverter" />
</ property >
</ bean >
<!-- 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 >
< property name ="messageConverter" ref ="messageConverter" />
</ bean >
二.单元测试有时加载 activemq的问题
1.这个可能和spring版本有关系,请采用比较稳定的版本。例如apache-activemq官方包里面提供的.
2.选择 xml解析的问题,例如
public
abstract
class
SpringManagerTestCase
extends
AbstractTransactionalDataSourceSpringContextTests {
public SpringManagerTestCase()
{
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl");
setDependencyCheck(false);
setDefaultRollback(false);
}
/** *//**
* 配置Spring的配置文件的方法。
* @see org.springframework.test.AbstractDependencyInjectionSpringContextTests#getConfigLocations()
*/
protected String[] getConfigLocations() {
return new String[] {"classpath:applicationContext-activemq-embedded.xml"};
}
}
AbstractTransactionalDataSourceSpringContextTests {
public SpringManagerTestCase()
{
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl");
setDependencyCheck(false);
setDefaultRollback(false);
}
/** *//**
* 配置Spring的配置文件的方法。
* @see org.springframework.test.AbstractDependencyInjectionSpringContextTests#getConfigLocations()
*/
protected String[] getConfigLocations() {
return new String[] {"classpath:applicationContext-activemq-embedded.xml"};
}
}
三.为特殊的应用服务器,如resin ,也要选择特定的xml解析器
在web.xml中配置增加
<
web-app
>
<!--
In order to be able to compatiable with Resin 2.1.x and 3.0.x,
both XML and XSLT have to be replaced.
If only xalan is included, Resin 2.1.x will fail but not 3.0.x.
Therefore the best way is to use the compatiable version of the
XML parser ans XSLT.
- Please refere to the following link for more detailed information.
- http://www.caucho.com/resin-3.0/xml/jaxp.xtp
-->
<!-- xml -->
< system-property javax.xml.parsers.DocumentBuilderFactory =
"org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" />
< system-property javax.xml.parsers.SAXParserFactory =
"org.apache.xerces.jaxp.SAXParserFactoryImpl" />
<!-- xslt -->
< system-property javax.xml.transform.TransformerFactory =
"org.apache.xalan.processor.TransformerFactoryImpl" />
</ web-app >
<!--
In order to be able to compatiable with Resin 2.1.x and 3.0.x,
both XML and XSLT have to be replaced.
If only xalan is included, Resin 2.1.x will fail but not 3.0.x.
Therefore the best way is to use the compatiable version of the
XML parser ans XSLT.
- Please refere to the following link for more detailed information.
- http://www.caucho.com/resin-3.0/xml/jaxp.xtp
-->
<!-- xml -->
< system-property javax.xml.parsers.DocumentBuilderFactory =
"org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" />
< system-property javax.xml.parsers.SAXParserFactory =
"org.apache.xerces.jaxp.SAXParserFactoryImpl" />
<!-- xslt -->
< system-property javax.xml.transform.TransformerFactory =
"org.apache.xalan.processor.TransformerFactoryImpl" />
</ web-app >
以上的以全部在实施中测试通过并且运行。大家可以方向使用和理解。如有疑问,相互交流.