上傳通訊薄操作,除了向客戶端返回好友列表外,還需要將上傳的通訊簿存儲到數(shù)據(jù)庫中,以便進(jìn)行后期數(shù)據(jù)分析。一開始,我的設(shè)計(jì)是將通訊薄全部插到數(shù)據(jù)庫后再返回客戶端,但經(jīng)過測試,用戶訪問速度過慢,于是我就采用多線程處理的方式,單開一個(gè)線程,在后臺慢慢插去吧,不影響客戶端訪問速度就行。我對多線程也不是太熟悉,代碼設(shè)計(jì)是參考碩碩的,由于時(shí)間緊,也沒多思考,雖然用得心里有點(diǎn)不踏實(shí)。
今早剛到公司就被游游責(zé)問,“通訊薄存數(shù)據(jù)庫開了多線程,你考慮線程安全了嗎”,志東也說,“開了多線程,如果線程池滿,怎么辦,數(shù)據(jù)會丟失的。。?!蔽抑荒軐?shí)話實(shí)說,當(dāng)時(shí)確實(shí)沒考慮線程安全問題,代碼參考自碩碩。。。志東生氣了,“張碩是錯(cuò)的你也抄!”。。。我頓時(shí)無語,只怨當(dāng)時(shí)開動線程的時(shí)候沒多考證一下。唉,痛定思痛,根據(jù)志東的建議:不要在Spring的Controller里開多線程,如果想進(jìn)行異步操作,可使用JMS。。。。
忙完令人超級蛋疼的LBS的bug,著手對上傳通訊薄JMS的優(yōu)化。看了半下午JMS,照著Demo,JMS算是跑起來了。具體配置下面將詳細(xì)闡述。
受教育的一天那。。。有時(shí),犯錯(cuò),確實(shí)會使人進(jìn)點(diǎn)步。
另:Spring的線程問題,到底怎么個(gè)情況,需要好好的搞一搞。線程池?多大?怎么設(shè)置的?SPring的線程模型?
對JMS的一些理解:
JMS有兩種工作模式,vm和tcp,使用vm模式時(shí),不必ActiveMQ服務(wù)器。使用tcp時(shí),需要使用ActiveMQ,從而建立Tcp鏈接。
ActiveMQ官網(wǎng)下載地址:
http://activemq.apache.org/download.html1. 使用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環(huán)境
略
3. 配置
這里主要介紹使用Spring監(jiān)聽來實(shí)現(xiàn)異步接受消息。
(1) applicationContext-jms.xml
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>
<!-- 隊(duì)列目的地-->
<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"/>
<!-- 設(shè)置默認(rèn)的消息目的地-->
<property name="defaultDestination" ref="myQueue"/>
<!-- 由于receiver方法是同步的,所以我們在這里對接收設(shè)置超時(shí)時(shí)間-->
<property name="receiveTimeout" value="60000"/>
</bean>
<!-- 消息發(fā)送者-->
<bean id="producer" class="com.sszd.springjms.JMSProducer">
<property name="jmsTemplate" ref="jmsTemplate"/>
<!-- 消息目的地,因?yàn)閖msTemplate有默認(rèn)的了,所以這里可以省略
<property name="destination" ref=" myQueue "/>-->
</bean>
<!-- 消息接收監(jiān)聽器用于異步接收消息-->
<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>
<!-- 消息監(jiān)聽實(shí)現(xiàn)方法一 -->
<bean id="studentMDP" class="com.sszd.springjms.StudentMDP"/>
<!-- 消息監(jiān)聽實(shí)現(xiàn)方法二,使用POJO -->
<bean id="pureMDPAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="pureStudentMDP"/>
<property name="defaultListenerMethod" value="process"/>
</bean>
<!-- 消息驅(qū)動pojo -->
<bean id ="pureStudentMDP" class="com.sszd.springjms.PureStudentMDP" >
<!--可以配置Spring的依賴
<property name="springOperation" ref="springOperation"/>
-->
</bean>
</beans>
(2) 消息生產(chǎn)者
Java代碼
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產(chǎn)生消息
*
*/
public class JMSProducer {
private JmsTemplate jmsTemplate;
public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
// 傳送一個(gè)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());
//也可以直接發(fā)送對象,對象必須是可序列化的
//ObjectMessage message = session.createObjectMessage();
//message.setObject(student);
return message;
}
});
}
}
(3) 消息接受監(jiān)聽器實(shí)現(xiàn)
方法一:
Java代碼
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;
/**
* 消息監(jiān)聽類
* */
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):
Java代碼
package com.sszd.springjms;
import java.util.Map;
import com.neu.edu.model.Student;
/**
*純POJO實(shí)現(xiàn)消息接收
* */
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) 業(yè)務(wù)層調(diào)用及配置
xml配置
Xml代碼
<bean name="jmsLogic" class="com.neu.edu.controllers.JMSLogic">
<property name="jmsProducer" ref="producer"/>
</bean>
業(yè)務(wù)層調(diào)用:
Java代碼
。。。
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("消息已經(jīng)發(fā)送.....");
}
}
。。。
4. 說明
本示例參考自百度文庫的資料(見附件Spring中使用JMS.pdf
http://wenku.baidu.com/view/98242d75f46527d3240ce0cc.html ),關(guān)于JMS的深入學(xué)習(xí),將在后續(xù)章節(jié)補(bǔ)充。
http://www.blogjava.net/heyang/archive/2009/09/24/296254.html