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注解开发之集合类型參数绑定 数组绑定 需 ...
随机推荐
- Delphi和JAVA用UTF-8编码进行Socket通信例子
最近的项目(Delphi开发),需要经常和java语言开发的系统进行数据交互(Socket通信方式),数据编码约定采用UTF-8编码. 令我无语的是:JAVA系统那边反映说,Delphi发的数据他们收 ...
- MySql之char与varchar
MySql之char与varchar的差别 char是一种固定长度的类型,varchar则是一种可变长度的类型.它们的差别是: 1. char(M)类型的数据列里.每一个值都占用M个字节.假设某个长 ...
- poj 2688 状态压缩dp解tsp
题意: 裸的tsp. 分析: 用bfs求出随意两点之间的距离后能够暴搜也能够用next_permutation水,但效率肯定不如状压dp.dp[s][u]表示从0出发訪问过s集合中的点.眼下在点u走过 ...
- qt的安装和debug
qt-opensource-windows-x86-msvc2013_64_opengl-5.3.0 这个已经包含了qt-creator-opensource-windows-x ...
- GIT分支管理是一门艺术
英文原文:http://www.nvie.com/posts/a-successful-git-branching-model/ 原文作者:Vincent Driessen 本文经Linux大棚博主总 ...
- Emmet语法
子代:> 如:div>ul>li <div> <ul> <li> </li> </ul> </div> 兄弟: ...
- docker镜像的操作
在主机上列出镜像 sudo docker images 每从Docker Hub下载一个镜像就会启动相对的创建一个容器 在镜像列表中看到三个重要的东西: 来自什么镜像源,例如ubuntu 每个镜像都有 ...
- iOS10 资料汇总:值得回看的 10 篇 iOS 热文
本文精选了 iOS大全 9月份的10篇热门文章.其中有软件推荐.技术分享及iOS10.Xcode8新特性等. 注:以下文章,点击标题即可阅读 <兼容iOS 10 资料整理笔记> 本文整理i ...
- jquery 和 $
而jQuery就是jQuery库提供的一个函数.(好像也不仅仅只是函数, 因为还有 $.ajax(options) 这样的使用,等同 jQuery.ajax(options)) 这个函数的作用是根据 ...
- BootStrap2学习日记20---定制缩略图
先看看效果: 代码: <ul class="thumbnails"> <li class="span3"> <div class= ...