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注解开发之集合类型參数绑定 数组绑定 需 ...
随机推荐
- [Ramda] Filter, Reject and Partition
We'll learn how to get a subset of an array by specifying items to include with filter, or items to ...
- [ES6] 14. Generator -- 1. yield & next()
Generators in ECMAscript 6 are first-class coroutines that produce encapsulated suspended execution ...
- Java模式(适配器模式)
今天看了下Java中的适配器模式,下面就来小做下总结和谈谈感想,以便日后使用. 首先,先来先讲讲适配器.适配就是由“源”到“目标”的适配,而其中链接两者的关系就是适配器.它负责把“源”过度到“目标”. ...
- Linux五种IO模型
http://www.cnblogs.com/renxs/p/3683189.html
- Jquery实现文本框获取焦点清空内容,失去焦点重新获得内容的公共函数
最近在做一个同城交友网站你给我吧(www.niyuewo.com)时写的一个函数与大家分享: //清除input中的内容 $(document).ready(function(){ $("i ...
- php demo
//上一周最后一天,上一个月最后一天: $y = date('Y',strtotime($endTime)); $m = date('m',strtotime($endTime)); ...
- windows 7 与linux 双系统 安装
注意事项: 1.安装Linux的时候,一定要选 “空闲”的硬盘去创建标准分区,否则会格式化C盘或D盘windows的资料.[如 /dev/sda1 为c盘主分区,sda2为扩展分区---下面有D盘,E ...
- C# Hook钩子实例代码之截取键盘输入,需要的朋友可以参考下
一.关于本文 以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: http://www.microsoft.com/china/community/program/origin ...
- Java开发核心技术面试心得分析
Java的数据结构有哪些?Map与Set的本质区别是什么? 分析:Java常见的数据结构有Collection和Map,其中Collection接口下包括List和Set接口,其下又有多个实现类如Li ...
- 结合源码看nginx-1.4.0之nginx多进程机制详解
目录 0. 摘要 1. nginx多进程设计思想 2. nginx多进程设计数据结构 3. nginx进程间通信机制 4. 一个简单的多进程例子 5. 小结 6. 参考源码