JMS在Spring框架下的应用
来源:互联网 发布:妮哩萌萌软件 编辑:程序博客网 时间:2024/05/21 22:56
今早刚到公司就被游游责问,“通讯薄存数据库开了多线程,你考虑线程安全了吗”,志东也说,“开了多线程,如果线程池满,怎么办,数据会丢失的。。。”我只能实话实说,当时确实没考虑线程安全问题,代码参考自硕硕。。。志东生气了,“张硕是错的你也抄!”。。。我顿时无语,只怨当时开动线程的时候没多考证一下。唉,痛定思痛,根据志东的建议:不要在Spring的Controller里开多线程,如果想进行异步操作,可使用JMS。。。。
忙完令人超级蛋疼的LBS的bug,着手对上传通讯薄JMS的优化。看了半下午JMS,照着Demo,JMS算是跑起来了。具体配置下面将详细阐述。
受教育的一天那。。。有时,犯错,确实会使人进点步。
另:Spring的线程问题,到底怎么个情况,需要好好的搞一搞。线程池?多大?怎么设置的?SPring的线程模型?
对JMS的一些理解:
JMS有两种工作模式,vm和tcp,使用vm模式时,不必ActiveMQ服务器。使用tcp时,需要使用ActiveMQ,从而建立Tcp链接。
ActiveMQ官网下载地址:http://activemq.apache.org/download.html
1. 使用jms所需的依赖包
activemq-all-5.3.0.jar
activemq-web-5.3.0.jar
geronimo-j2ee-management_1.0_spec-1.0.jar
geronimo-jms_1.1_spec-1.1.1.jar
geronimo-jta_1.0.1B_spec-1.0.1.jar
2. 搭好Spring环境
略
3. 配置
这里主要介绍使用Spring监听来实现异步接受消息。
(1) applicationContext-jms.xml
- <?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:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
- <!-- 消息中介-->
- <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
- <property name="brokerURL" value="vm://localhost"/>
- </bean>
- <!-- 队列目的地-->
- <bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">
- <constructor-arg index="0" value="notifyQueue"/>
- </bean>
- <!-- 订阅目的地-->
- <bean id="myTopic" class="org.apache.activemq.command.ActiveMQTopic">
- <constructor-arg index="0" value="notifyTopic"/>
- </bean>
- <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
- <property name="connectionFactory" ref="connectionFactory"/>
- <!-- 设置默认的消息目的地-->
- <property name="defaultDestination" ref="myQueue"/>
- <!-- 由于receiver方法是同步的,所以我们在这里对接收设置超时时间-->
- <property name="receiveTimeout" value="60000"/>
- </bean>
- <!-- 消息发送者-->
- <bean id="producer" class="com.sszd.springjms.JMSProducer">
- <property name="jmsTemplate" ref="jmsTemplate"/>
- <!-- 消息目的地,因为jmsTemplate有默认的了,所以这里可以省略
- <property name="destination" ref=" myQueue "/>-->
- </bean>
- <!-- 消息接收监听器用于异步接收消息-->
- <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
- <property name="connectionFactory" ref="connectionFactory"/>
- <property name="destination" ref="myQueue"/>
- <!-- <property name="messageListener" ref="studentMDP"/>-->
- <property name="messageListener" ref="pureMDPAdapter"/>
- </bean>
- <!-- 消息监听实现方法一 -->
- <bean id="studentMDP" class="com.sszd.springjms.StudentMDP"/>
- <!-- 消息监听实现方法二,使用POJO -->
- <bean id="pureMDPAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
- <property name="delegate" ref="pureStudentMDP"/>
- <property name="defaultListenerMethod" value="process"/>
- </bean>
- <!-- 消息驱动pojo -->
- <bean id ="pureStudentMDP" class="com.sszd.springjms.PureStudentMDP" >
- <!--可以配置Spring的依赖
- <property name="springOperation" ref="springOperation"/>
- -->
- </bean>
- </beans>
<?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:context="http://www.springframework.org/schema/context"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><!-- 消息中介--><bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"><property name="brokerURL" value="vm://localhost"/></bean><!-- 队列目的地--><bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue"><constructor-arg index="0" value="notifyQueue"/></bean><!-- 订阅目的地--><bean id="myTopic" class="org.apache.activemq.command.ActiveMQTopic"><constructor-arg index="0" value="notifyTopic"/></bean><bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"><property name="connectionFactory" ref="connectionFactory"/><!-- 设置默认的消息目的地--><property name="defaultDestination" ref="myQueue"/><!-- 由于receiver方法是同步的,所以我们在这里对接收设置超时时间--><property name="receiveTimeout" value="60000"/></bean><!-- 消息发送者--><bean id="producer" class="com.sszd.springjms.JMSProducer"><property name="jmsTemplate" ref="jmsTemplate"/><!-- 消息目的地,因为jmsTemplate有默认的了,所以这里可以省略<property name="destination" ref=" myQueue "/>--></bean><!-- 消息接收监听器用于异步接收消息--><bean class="org.springframework.jms.listener.SimpleMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory"/><property name="destination" ref="myQueue"/><!-- <property name="messageListener" ref="studentMDP"/>--><property name="messageListener" ref="pureMDPAdapter"/></bean><!-- 消息监听实现方法一 --><bean id="studentMDP" class="com.sszd.springjms.StudentMDP"/><!-- 消息监听实现方法二,使用POJO --><bean id="pureMDPAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"><property name="delegate" ref="pureStudentMDP"/><property name="defaultListenerMethod" value="process"/></bean><!-- 消息驱动pojo --><bean id ="pureStudentMDP" class="com.sszd.springjms.PureStudentMDP" ><!--可以配置Spring的依赖<property name="springOperation" ref="springOperation"/>--></bean></beans>
(2) 消息生产者
- package com.sszd.springjms;
- import javax.jms.JMSException;
- import javax.jms.MapMessage;
- import javax.jms.Message;
- import javax.jms.Session;
- import org.springframework.jms.core.JmsTemplate;
- import org.springframework.jms.core.MessageCreator;
- import com.neu.edu.model.Student;
- /**
- * 利用Spring中的JmsTemplate产生消息
- *
- */
- public class JMSProducer {
- private JmsTemplate jmsTemplate;
- public JmsTemplate getJmsTemplate() {
- return jmsTemplate;
- }
- public void setJmsTemplate(JmsTemplate jmsTemplate) {
- this.jmsTemplate = jmsTemplate;
- }
- // 传送一个Student 对象(重写了toString()方法)
- public void send(final Student student) {
- this.jmsTemplate.send(new MessageCreator() {
- public Message createMessage(Session session) throws JMSException {
- MapMessage message = session.createMapMessage();
- message.setString("key1", student.getName());
- message.setString("key2", student.getAge());
- //也可以直接发送对象,对象必须是可序列化的
- //ObjectMessage message = session.createObjectMessage();
- //message.setObject(student);
- return message;
- }
- });
- }
- }
package com.sszd.springjms;import javax.jms.JMSException;import javax.jms.MapMessage;import javax.jms.Message;import javax.jms.Session;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import com.neu.edu.model.Student;/** * 利用Spring中的JmsTemplate产生消息 * */public class JMSProducer {private JmsTemplate jmsTemplate;public JmsTemplate getJmsTemplate() {return jmsTemplate;}public void setJmsTemplate(JmsTemplate jmsTemplate) {this.jmsTemplate = jmsTemplate;}// 传送一个Student 对象(重写了toString()方法)public void send(final Student student) {this.jmsTemplate.send(new MessageCreator() {public Message createMessage(Session session) throws JMSException {MapMessage message = session.createMapMessage();message.setString("key1", student.getName());message.setString("key2", student.getAge()); //也可以直接发送对象,对象必须是可序列化的 //ObjectMessage message = session.createObjectMessage(); //message.setObject(student);return message;}});}}
(3) 消息接受监听器实现
方法一:
- package com.sszd.springjms;
- import javax.jms.JMSException;
- import javax.jms.MapMessage;
- import javax.jms.Message;
- import javax.jms.MessageListener;
- import com.neu.edu.model.Student;
- /**
- * 消息监听类
- * */
- public class StudentMDP implements MessageListener {
- public void onMessage(Message message) {
- MapMessage mapMessage = (MapMessage) message;
- Student student = new Student();
- try {
- student.setName(mapMessage.getString("key1"));
- student.setAge(mapMessage.getString("key2"));
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(student.getName());
- } catch (JMSException e) {
- e.printStackTrace();
- }
- }
- }
package com.sszd.springjms;import javax.jms.JMSException;import javax.jms.MapMessage;import javax.jms.Message;import javax.jms.MessageListener;import com.neu.edu.model.Student;/** * 消息监听类 * */public class StudentMDP implements MessageListener {public void onMessage(Message message) {MapMessage mapMessage = (MapMessage) message;Student student = new Student();try {student.setName(mapMessage.getString("key1"));student.setAge(mapMessage.getString("key2"));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(student.getName());} catch (JMSException e) {e.printStackTrace();}}}
方法二(使用POJO):
- package com.sszd.springjms;
- import java.util.Map;
- import com.neu.edu.model.Student;
- /**
- *纯POJO实现消息接收
- * */
- public class PureStudentMDP {
- //private PoiDataFromProviderService poiDataFromProviderService;可以添加Spring依赖注入
- public void process(Map map) {
- Student student = new Student();
- student.setName((String) map.get("key1"));
- student.setAge((String) map.get("key2"));
- System.out.println("PureStudentMDP:");
- System.out.println(student);
- }
- /*可以直接接收对象
- public void process(Objec obj) {
- Student student = (Student)obj;
- System.out.println(student);
- }
- */
- }
package com.sszd.springjms;import java.util.Map;import com.neu.edu.model.Student;/** *纯POJO实现消息接收 * */public class PureStudentMDP {//private PoiDataFromProviderService poiDataFromProviderService;可以添加Spring依赖注入public void process(Map map) {Student student = new Student();student.setName((String) map.get("key1"));student.setAge((String) map.get("key2"));System.out.println("PureStudentMDP:");System.out.println(student);}/*可以直接接收对象public void process(Objec obj) {Student student = (Student)obj;System.out.println(student);}*/}
(4) 业务层调用及配置
xml配置
- <bean name="jmsLogic" class="com.neu.edu.controllers.JMSLogic">
- <property name="jmsProducer" ref="producer"/>
- </bean>
<bean name="jmsLogic" class="com.neu.edu.controllers.JMSLogic"><property name="jmsProducer" ref="producer"/></bean>
业务层调用:
- 。。。
- private JMSProducer jmsProducer;
- public void upload() {
- 。。。
- Student student = new Student();
- for (int i = 0; i < 15; i++) {
- student.setName("zzq" + i);
- student.setAge("25");
- jmsProducer.send(student);
- System.out.println("消息已经发送.....");
- }
- }
- 。。。
。。。 private JMSProducer jmsProducer;public void upload() {。。。Student student = new Student();for (int i = 0; i < 15; i++) {student.setName("zzq" + i);student.setAge("25");jmsProducer.send(student);System.out.println("消息已经发送.....");}} 。。。
4. 说明
本示例参考自百度文库的资料(见附件Spring中使用JMS.pdf http://wenku.baidu.com/view/98242d75f46527d3240ce0cc.html ),关于JMS的深入学习,将在后续章节补充。
http://www.blogjava.net/heyang/archive/2009/09/24/296254.html
- JMS在Spring框架下的应用
- Spring JMS 整合Weblogic JMS(weblogicMQ)后在tomcat下运行报错的解决
- spring Batch在SSH框架的应用
- Web应用中基于组的用户权限管理在Spring框架下的实现
- Spring JMS应用
- Spring JMS应用
- jms在jboss上的简单应用
- DirectX 在MFC框架下的应用
- WebSocket在各种框架下的应用
- redis在spring下的应用
- 简单明了地解释JMS , 相关概念 ,以及JMS的实例代码下载 ,传统使用方式(非Spring框架下的集成)
- 本篇主要讲解在未使用其他框架(Spring)整合情况下,独立基于ActiveMQ,使用JMS规范进行消息通信。
- 在spring中使用jms
- 在Spring中使用JMS
- spring 下 配置jms messageListener 的事务及相关问题
- jms 的应用
- jms的简单应用
- mq, jms的应用
- Quick-sort
- GUI程序控制台输出调试信息
- ibatis 中 $与#的区别
- magento URL分析,查找修改相应文件
- CnForums学习
- JMS在Spring框架下的应用
- leetcode: Sort Colors
- 在Java中的使用RSA
- 九度1002
- 内存泄露检测类
- NSFetchedResultsController 与 UITableView 的问题
- csdn博客需要审核了,怎么活
- 响应式设计与CSS3媒体查询
- c#异步编程&&HttpClient类体验