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++ Code_animateCtrl
Code:: 播放 if (!m_animate1.Open("C:\\copy.avi")) { MessageBox("NULL& ...
- Android ListView标题置顶效果实现
一. 有图有真相 二.实现: 1. 基于ListView分类效果 2. TitleView即标题的处理(创建) 3. 处理TitleView的三种状态 三.源码: 例子下载 实现可以看代码,具 ...
- Java Web模块——验证码模块
一.什么是验证码及它的作用 验 证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答. 可以防止恶意破解密码. ...
- NBUT 1225 NEW RDSP MODE I
找出循环周期即可了 #include<bits/stdc++.h> using namespace std; int N,M,X; int time(int x,int y,int z) ...
- 比较全面的MySQL优化参考
本文整理了一些MySQL的通用优化方法,做个简单的总结分享,旨在帮助那些没有专职MySQL DBA的企业做好基本的优化工作,至于具体的SQL优化,大部分通过加适当的索引即可达到效果,更复杂的就需要 ...
- Linux网卡高级命令、IP别名及多网卡绑定 转
http://www.cnblogs.com/xiaoluo501395377/archive/2013/05/26/3100065.html 本篇随笔将详细讲解Linux系统的网卡高级命令.IP别名 ...
- linux php安装扩展方法 查找配置文件
如何在linux中查看nginx.apache.php.mysql配置文件路径了,如果你接收一个别人配置过的环境,但没留下相关文档.这时该怎么判断找到正确的加载文件路径了.可以通过以下来判断 1.判断 ...
- 如何设计App登录模块?
1.熟悉目前常见的手机APP登陆方式 ① 账号登陆(手机.邮箱) ② 第三方登陆(微信,QQ,微博) ③ 一键快捷登录(工具类,如不记单词) ④ 游客登陆(bbs) ⑤ demo测试登陆(如友盟等) ...
- [Arduino] 在串口读取多个字符串,并且转换为数字数组
功能如题目.在串口收到逗号分割的6串数字比如100,200,45,4,87,99然后在6个PWM端口3, 5, 6, 9, 10, 11输出对应PWM值代码注释很详细了,就不再说明了. //定义一个c ...
- 【Linux】Shell脚本编程(二)
练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 for i in $(seq 0 2 ...