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注解开发之集合类型參数绑定 数组绑定 需 ...
随机推荐
- 全面整理的C++面试题
C++面试题 1.是不是一个父类写了一个virtual 函数,假设子类覆盖它的函数不加virtual ,也能实现多态? virtual修饰符会被隐形继承的. private 也被集成,仅仅事派生类没有 ...
- Android微信SDK API 调用教程【转】
原文:http://blog.csdn.net/worker90/article/details/8211451 最近一直在调用微信的API,却发现一直调用不成功,纠结了好久,各方面找教程,找官方,官 ...
- 关于View端
View--------------Request 1 URL vs n View 同一个URL可以对应多个View, HTML(通过Request请求获得) 例如SAO项目中的step1--> ...
- 云服务器 ECS Linux 误删除文件恢复方法介绍
云服务器 ECS Linux 下,rm -rf 意味着一旦删除的文件是无法挽回的.但如果在没有文件覆盖操作的前提下,可以先尝试相关方式进行文件恢复. 本文对此进行简要说明. https://help ...
- 关于Android悬浮窗要获取按键响应的问题
要在Android中实现顶层的窗口弹出,一般都会用WindowsManager来实现,但是几乎所有的网站资源都是说弹出的悬浮窗不用接受任何按键响应. 而问题就是,我们有时候需要他响应按键,比如电视上的 ...
- 1.5.1 Analyzers,Tokenizers,Filters概述
字段分析器(Analyzers)即用于文档索引也用于查询.一个分析器检查字段的文本,并生成一个token流.分析器可能是一个单独的类,也可能是一系列的tokenizer和filter的组合. 分词器把 ...
- 一、Android应用程序的基本原理(Fundamentals [,fʌndə'mentlz])
Android 应用程序以java作为编程语言.Android SDK工具把代码连同数据.资源文件一起编译成一个以.apk为后缀(suffix)的android 程序存档(archive)文件包.在一 ...
- jquery插件开发规范
一.请给你的代码加上注释 这个世界不存在百分百的完美的jquery插件,注释不止是给别人看.更重要的是给自己看. 你应该把注释当做你代码的一部分,养成随手加注释的习惯,尤其是编写javascript的 ...
- 写多个物件css3循环动画案例原理
div { background-color: #67CF22; height: 100%; width: 6px; display: inline-block; -webkit-animation: ...
- 证明Dijkstra中加入S的点已经最优
语言抽象,仅供自用. 证明一个即将加入S集合的点u必然D[u]=最小值min: 假设D[u] != 最小值,那么即说明存在一条最短路径,该路径可以描述为:S集合中的一个点(至少为起始点) + 一个 ...