AMQ学习笔记 - 13. Spring-jms的配置
概述
producer端
spring配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean> <!-- create template for send message -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- bind the connection factory -->
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestinationName" value="jms-config" />
</bean>
</beans>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- bind the connection factory -->
<property name="connectionFactory" ref="connectionFactory" />
<property name="pubSubDomain" value="true" />
<property name="defaultDestinationName" value="jms-config" />
</bean>
测试类
package cn.sinobest.asj.producer.springsupport.jt;
import javax.annotation.Resource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) // 配置spring组件运行时
@ContextConfiguration("/spring-jms-demo.xml") // 配置文件
public class JmsTemplateSendWithContextTest {
@Resource(name = "jmsTemplate")
private JmsTemplate jt; @Test
public void testSendToDefaultDestination() {
String message = "you can config JmsTemplate in xml, then use it for send.";
jt.convertAndSend(message);
}
}
展示这个测试类,是想告诉大家使用Spring+JUnit4的注解编写单元测试,可以非常方便的加载Spring配置并初始化bean资源;使用Resource注解可以获取bean资源。如何使用JmsTemplate来发送消息,反而不是重点,因为在08. Spring-JmsTemplate之发送中,已经详细介绍了相关的API。
consumer端
同步接收
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- bind the connection factory -->
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestinationName" value="jms-config" />
<property name="receiveTimeout" value="3000" />
</bean>
异步接收
传统的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean> <bean id="messageListener" class="cn.sinobest.asj.consumer.springsupport.async.SimpleMessageListener" />
<bean id="messageContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationName" value="jms-config" />
<property name="messageListener" ref="messageListener" />
</bean>
</beans>
其中,SimpleMessageListener是接口javax.jms.MessageListener的实现类。
1.Destination及类型
|
2.多线程
|
3.确认模式
|
4.事务
|
精简的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean> <bean id="messageListener" class="cn.sinobest.asj.consumer.springsupport.async.SimpleMessageListener" />
<bean id="messageContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationName" value="jms-config" />
<property name="messageListener" ref="messageListener" />
</bean>
</beans>
1.Destination类型
2.pojo监听器
package cn.sinobest.asj.consumer.springsupport.async; /**
* 一个pojo作为listener,接收经过转换后的消息.
* @author lijinlong
*
*/
public class PojoListener {
public void passMeMessage(String message) {
System.out.println("从queue收到消息:" + message);
}
}
3.多线程
4.确认模式和事务4
可信任的包
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="trustedPackages">
<list>
<!-- you must add the package or parent-package of object which is put in ObjectMessage -->
<value>java.lang</value>
<value>java.sql</value>
<value>cn.sinobest</value>
</list>
</property>
</bean>
ConnectionFactory的bean配置
1.ActiveMQConnectionFactory
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
2.SingleConnectionFactory
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
</bean>
3.PooledConnectionFactory
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
</bean>
分布式事务
1.broker-A到broker-B
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- part-1 -->
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean> <tx:annotation-driven transaction-manager="jtaTransactionManager" /> <!-- part-2 -->
<bean id="sourceConnFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
<property name="uniqueResourceName" value="broker/source" />
<property name="xaConnectionFactory">
<bean class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:57015" />
</bean>
</property>
<property name="maxPoolSize" value="10" />
</bean> <bean id="targetConnFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
<property name="uniqueResourceName" value="broker/target" />
<property name="xaConnectionFactory">
<bean class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
<property name="maxPoolSize" value="10" />
</bean> <bean id="sourceJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="sourceConnFactory" />
<property name="defaultDestinationName" value="asj.log" />
<property name="receiveTimeout" value="3000" />
<property name="sessionTransacted" value="true" />
</bean> <bean id="targetJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="targetConnFactory" />
<property name="defaultDestinationName" value="asj.log" />
<property name="sessionTransacted" value="true" />
</bean>
</beans>
服务类获取sourceJmsTemplate、targetJmsTemplate,在业务方法中使用前者接收消息,使用后者发送消息。业务代码要注解为org.springframework.transaction.annotation.Transactional:
@Transactional
public boolean transport() throws JmsException{
Message remsg = souJT.receive();
if (remsg != null) {
final ObjectMessage omsg = (ObjectMessage) remsg; tarJT.send(new MessageCreator() {
public Message createMessage(Session session)
throws JMSException {
Message result = session.createObjectMessage(omsg
.getObject());
return result;
}
});
}
return remsg != null;
}
实际上,我虽然在项目里用了上面的配置,但是对其原理却不了解。另外有2个问题值得一说:
- 定时任务和事务的冲突
服务类是事务的,如果它同时作为定时任务,会有问题;后来把定时任务独立了出来,定时调用服务类的业务方法。 - 事务和循环的冲突
本来计划在事务中使用循环,以souJT接收到的消息为null作为结束条件,每接收一条就发送一条。结果即使有更多的消息,也只执行一次,是不是由Atomikos造成的也无从知晓。后来就把循环放在了定时任务里,在循环体调用业务方法,根据返回的结果来判断是否结束循环。
2.broker-B到数据库
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.2.xsd">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${java.naming.provider.url}" />
</bean> <bean id="converteredLogListener" class="cn.sinobest.asj.log.listener.ConverteredLogListener" /> <jms:listener-container connection-factory="connectionFactory"
concurrency="1" acknowledge="transacted">
<jms:listener destination="asj.log" ref="converteredLogListener"
method="onLog" />
</jms:listener-container>
</beans>
当然,我们必须声明listener-container的acknowledge属性为"transacted",以开启事务。在ConverteredLogListener的onLog,调用服务组件将数据入库,只要写入失败时抛出的异常能抵达onLog方法,事务就会回滚,所以请确保异常能抛出来。
AMQ学习笔记 - 13. Spring-jms的配置的更多相关文章
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring Bean的配置及常用属性
作为 Spring 核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由 Spring 容器完成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦.这一切都离不 ...
- Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法
Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...
- SQL反模式学习笔记13 使用索引
目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引. 索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...
- Spring实战第八章学习笔记————使用Spring Web Flow
Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...
- Spring实战第五章学习笔记————构建Spring Web应用程序
Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- golang学习笔记13 Golang 类型转换整理 go语言string、int、int64、float64、complex 互相转换
golang学习笔记13 Golang 类型转换整理 go语言string.int.int64.float64.complex 互相转换 #string到intint,err:=strconv.Ato ...
- springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定
springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...
随机推荐
- [Angular2 Router] Use Params from Angular 2 Routes Inside of Components
Angular 2’s ActivatedRoute allows you to get the details of the current route into your components. ...
- ActivityGroup+LinearLayout实现iphone风格的底部tab菜单
public class ActsGroup extends ActivityGroup { private LinearLayout bodyView; private Line ...
- iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果
8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...
- 和iPhone有关的视图控制器:UIViewController、UITabBarController、UINavigationController及其混合用法
iPhone中的view视图是应用程序对于数据最直观.最直接的呈现方式,如下是我在学习了iPhone中的视图控制器以及由其衍生的特殊子类的总结,希望对那些初学者有所帮助: UIViewControll ...
- 终端I/O之终端选项标志
http://www.cnblogs.com/nufangrensheng/p/3575752.html 中的表18-1至表18-4中列出的所有选项标志(除屏蔽标志外)都用一位或几位(设置或清除)表示 ...
- set与hash_set
原文:http://blog.csdn.net/morewindows/article/details/7029587 STL系列之六 set与hash_set set和hash_set是STL中比较 ...
- IOS开发之--异常处理--使用try 和 catch 来捕获错误。
一个搞java的老板问我会不会try catch 我说不会 学这么久也没听周围朋友用这个 因为苹果控制台本来就可以打印异常 特此研究一下. 1.try catch: 是捕获异常代码段 特点:对 ...
- iOS uiscrollView 嵌套 问题 的解决
苹果官方文档里面提过,最好不要嵌套scrollView,特别提过UITableView和UIWebView,因为在滑动时,无法知道到底是希望superScrollView滑动还是subScrollVi ...
- OnTouchListener事件监听实现方式之GestureDetector
当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等. 一般情况下,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouc ...
- android 中对于采用okhttp时获取cookie并放入webview实现跳过登陆显示页面的功能
最近项目需要将网页的一些信息展示到app当中,由于采用的是okhttp进行网络的访问,并采用了cookie对于每次的访问请求都做了验证,所以在加入webview显示网页的时候会需要进行一下验证,为了跳 ...