JMS在Spring框架下的应用

  上传通讯薄操作,除了向客户端返回好友列表外,还需要将上传的通讯簿存储到数据库中,以便进行后期数据分析。一开始,我的设计是将通讯薄全部插到数据库后再返回客户端,但经过测试,用户访问速度过慢,于是我就采用多线程处理的方式,单开一个线程,在后台慢慢插去吧,不影响客户端访问速度就行。我对多线程也不是太熟悉,代码设计是参考硕硕的,由于时间紧,也没多思考,虽然用得心里有点不踏实。

    今早刚到公司就被游游责问,“通讯薄存数据库开了多线程,你考虑线程安全了吗”,志东也说,“开了多线程,如果线程池满,怎么办,数据会丢失的。。。”我只能实话实说,当时确实没考虑线程安全问题,代码参考自硕硕。。。志东生气了,“张硕是错的你也抄!”。。。我顿时无语,只怨当时开动线程的时候没多考证一下。唉,痛定思痛,根据志东的建议:不要在Spring的Controller里开多线程,如果想进行异步操作,可使用JMS。。。。

    基于Spring 项目的JMS 具体配置:

    对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>

    (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; 
                }
            });  
        }
}

(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();
        }
    }
}

方法二(使用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);
    }
}

 (4) 业务层调用及配置

xml配置

<bean name="jmsLogic" class="com.neu.edu.controllers.JMSLogic">
    <property name="jmsProducer" ref="producer"/>
</bean>

业务层调用:

Java代码 

private JMSProducer jmsProducer;

public void upload(){
        Student student=new Student();
        for(int i=0;i<15;i++){
            student.setAge("25");
            jmsProducer.send(student);
            System.out.println("消息已经发送.....");
         }
}

转载于:https://my.oschina.net/mclimber/blog/1510710

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值