结合Spring20和ActiveMQ进行异步消息调用完善自我超越自我七杀家园 Web开发者的博客Powered By.docx
《结合Spring20和ActiveMQ进行异步消息调用完善自我超越自我七杀家园 Web开发者的博客Powered By.docx》由会员分享,可在线阅读,更多相关《结合Spring20和ActiveMQ进行异步消息调用完善自我超越自我七杀家园 Web开发者的博客Powered By.docx(12页珍藏版)》请在冰豆网上搜索。
结合Spring20和ActiveMQ进行异步消息调用完善自我超越自我七杀家园Web开发者的博客PoweredBy
结合Spring2.0和ActiveMQ进行异步消息调用-完善自我,超越自我-七杀家园Web开发者的博客-PoweredByPHPWind.Net
在Spring2.0之前,Spring的JMS的作用局限于产生消息。
这个功能(封装在JmsTemplate类中)当然是很好的,
但是,它没有描述完整的JMS堆栈,比如像消息的异步产生和消耗。
JMS堆栈缺少的这一部分已经被添加,Spring2.0现在提供对消息异步消耗的完整支持。
让我们从一个例子开始。
首先我们打开ActiveMQ。
从ActiveMQ的安装路径上的bin目录,那里有一个ActiveMQ.bat,双击执行即可。
不过要注意必须先设置java_home环境变量。
ActiveMQ默认的服务端口是61616。
然后我们开始配置Spring配置文件。
我起名为spring-jms.xml首先要配置一个ConnectionFactory代码如下
Copycode
<beanid="connectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<propertyname="brokerURL"value="tcp:
//localhost:
61616"/>
</bean>
这里用到的ConnectionFactory是ActiveMQ提供的工厂,为了能使用这个工厂,我们必须在项目中添加以下几个jar文件:
geronimo-jms_1.1_spec-1.0.jar,
activeio-core-3.0-beta3.jar,
activemq-core-4.0.1.jar,
backport-util-concurrent-2.1.jar,
commons-logging-1.0.4.jar,
geronimo-j2ee-management_1.0_spec-1.0.jar
以上这些Jar文件都存在于ActiveMQ安装目录的lib目录下,这些可是我一个一个试验出来的,累个半死。
。
然后应该配置一个Queue(我使用的是点对点方式),不过ActiveMQ只要提供一个名字就可以自动创建队列,因此这一步省了,呵呵
下
面就轮到Spring的支持类了,首先是JmsTemplate。
这个类提供了大量的方法简化我们对JMS的操作。
常用的有两个,
org.springframework.jms.core.JmsTemplate102和
org.springframework.jms.core.JmsTemplate,这两个类分别支持JMS的1.02版本和1.1版本。
现在比较常用
的还是1.02版本。
配置如下
Copycode<beanid="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate102">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="timeToLive"value="86400000"/>
<propertyname="defaultDestinationName"value="cmpp"/>
<propertyname="messageConverter"ref="messageConverter"/>
<propertyname="receiveTimeout"value="30000"/>
</bean>上
面的配置中用到了第一步配置的connectionFactory以及一个消息转换的类messageConverter,这个类实现了
org.springframework.jms.support.converter.MessageConverter接口,可以在消息发送之前和接
受之后进行消息类型转换。
具体的看最后的实例代码。
配置代码如下:
Copycode
<!
--SpringJMSSimpleConverter-->
<beanid="simpleConverter"class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
<!
--MessageConverter-->
<beanid="messageConverter"
class="com.liangj.apmgt.jms.ApmgtMessageConverter">
<propertyname="converter">
<reflocal="simpleConverter"/>
</property>
</bean>这里还配置了发送的消息的存在时间timeToLive,目标Queue的名字defaultDestinationName,接受消息超时时间receiveTimeout
配置发送代码
Copycode
<!
--Messageporducer-->
<beanid="producer"
class="com.liangj.apmgt.jms.DefaultApmgtMessageProducer">
<propertyname="jmsTemplate"ref="jmsTemplate"/>
</bean>接着配置监听器,这是Spring2.0新增的功能,配置如下:
Copycode
<!
--thisistheMessageDrivenPOJO(MDP)-->
<beanid="messageListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean
class="com.liangj.apmgt.jms.DefaultApmgtMessageListener"/>
</constructor-arg>
<propertyname="defaultListenerMethod"value="onMessage"/>
<propertyname="messageConverter"ref="messageConverter"/>
</bean><!
--andthisistheattendantmessagelistenercontainer-->
<beanid="listenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destinationName"value="${jms.destinationName.cmpp}"/>
<propertyname="messageSelector"value="${jms.messageSelector}"/>
<propertyname="messageListener"ref="messageListener"/>
</bean>
Spring配置监听器有很多种选择,在这里我选择这回种MessageListenerAdapter方法主要是因为这个方法比较灵活。
实现他只要一个
很普通的java类即可,和JMS以及Spring的耦合度最低。
其中方法onMessage可以随便修改方法名,只要在配置文件中对应的修改就好了。
MessageListenerAdapter还有一个功能就是如果处理方法(我这里是onMessage)返回一个非空值,它将自动返回一个响应消息。
这个消息会返回给JMSReply-To属性定义的目的地(如果存在),或者是MessageListenerAdapter设置(如果配置了)的缺省目的地;如果没有定义目的地,那么将产生一个InvalidDestinationException异常(此异常将不会只被捕获而不处理,它将沿着调用堆栈上传)。
这样我们的配置就都完成了。
接下来我们来实现对应的Java文件
先是接口文件发送消息接口IApmgtMessageProducer.java
Copycode
publicinterfaceIApmgtMessageProducer{
publicabstractvoidsendMessage(ApmgtMessageDatamessageData);
}接受消息接口IApmgtMessageListener.java
Copycode
publicinterfaceIApmgtMessageListener{
publicvoidonMessage(ApmgtMessageDatamessage);
}发消息的文件DefaultApmgtMessageProducer.java
Copycode
publicclassDefaultApmgtMessageProducerimplementsIApmgtMessageProducer{
privateJmsTemplatejmsTemplate;publicvoidsetJmsTemplate(JmsTemplatejmsTemplate){
this.jmsTemplate=jmsTemplate;
}publicvoidsendMessage(ApmgtMessageDatamessageData){
this.jmsTemplate.convertAndSend(messageData);
}
}收消息文件DefaultApmgtMessageListener.java
Copycode
publicclassDefaultApmgtMessageListenerimplementsIApmgtMessageListener{
publicvoidonMessage(ApmgtMessageDatamessage){
System.out.println("监听到消息:
"+message);
}
}消息转换类ApmgtMessageConverter.java
Copycode
publicclassApmgtMessageConverterimplementsMessageConverter{privateLoglog=LogFactory.getLog(ApmgtMessageConverter.class);privateSimpleMessageConverterconverter;publicvoidsetConverter(SimpleMessageConverterconverter){
this.converter=converter;
}publicObjectfromMessage(Messagemessage)throwsJMSException,MessageConversionException{
if(messageinstanceofObjectMessage){
ObjectMessageo_message=(ObjectMessage)message;
MessageHeaderheader=newMessageHeader();
header.setId(message.getLongProperty("id"));
header.setReceiver(message.getIntProperty("receiver"));
header.setSender(message.getIntProperty("sender"));
header.setSendPerson(message.getStringProperty("sendPerson"));
header.setType(message.getIntProperty("type"));
SerializablemessageContent=o_message.getObject();
ApmgtMessageData<Serializable>messageData=newApmgtMessageData<Serializable>();
messageData.setMessageContent(messageContent);
messageData.setMessageHeader(header);
returnmessageData;
}
returnnull;
}publicMessagetoMessage(Objectobject,Sessionsession)throwsJMSException,MessageConversionException{
if(objectinstanceofApmgtMessageData){
ApmgtMessageDatadata=(ApmgtMessageData)object;
Messagemessage=converter.toMessage(data.getMessageContent(),session);
message.setLongProperty("id",data.getMessageHeader().getId());
message.setIntProperty("receiver",data.getMessageHeader().getReceiver());
message.setIntProperty("sender",data.getMessageHeader().getSender());
message.setIntProperty("type",data.getMessageHeader().getType());
message.setStringProperty("sendPerson",data.getMessageHeader().getSendPerson());
log.info("发送消息[MessageSender]:
\n"+message);
returnmessage;
}else{
returnnull;
}
}}消息类文件消息父类:
ApmgtMessageData.java
Copycode
publicclassApmgtMessageData<TextendsSerializable>{protectedTmessageContent;
protectedMessageHeadermessageHeader;publicTgetMessageContent(){
returnthis.messageContent;
}publicMessageHeadergetMessageHeader(){
returnthis.messageHeader;
}publicvoidsetMessageContent(TmessageContent){
this.messageContent=messageContent;
}
publicvoidsetMessageHeader(MessageHeadermessageHeader){
this.messageHeader=messageHeader;
}}消息属性的一个类MessageHeader.java
Copycode
publicclassMessageHeader{/**
*消息ID
*/
privatelongid;/**
*消息类型
*/
privateinttype;/**
*消息发送方,发送消息的模块
*/
privateintsender;/**
*消息接收方,接收消息的模块
*/
privateintreceiver;/**
*消息发送者,具体的用户
*/
privateStringsendPerson;publicMessageHeader(){
this.id=System.currentTimeMillis();
}
publiclonggetId(){
returnid;
}publicvoidsetId(longid){
this.id=id;
}publicStringgetSendPerson(){
returnsendPerson;
}publicvoidsetSendPerson(StringsendPerson){
this.sendPerson=sendPerson;
}publicintgetReceiver(){
returnreceiver;
}publicvoidsetReceiver(intreceiver){
this.receiver=receiver;
}publicintgetSender(){
returnsender;
}publicvoidsetSender(intsender){
this.sender=sender;
}publicintgetType(){
returntype;
}publicvoidsetType(inttype){
this.type=type;
}}消息体的类ModPasswordRequest.java
Copycode
publicclassModPasswordRequestimplementsSerializable{privatestaticfinallongserialVersionUID=1L;/**
*旧密码
*/
privateStringoldPassword;
/**
*新密码
*/
privateStringnewPassword;publicStringgetNewPassword(){
returnnewPassword;
}publicvoidsetNewPassword(StringnewPassword){
this.newPassword=newPassword;
}publicStringgetOldPassword(){
returnoldPassword;
}publicvoidsetOldPassword(StringoldPassword){
this.oldPassword=oldPassword;
}}消息类:
ApmgtModPasswordRequest.java
Copycode
publicclassApmgtModPasswordRequestextendsApmgtMessageData<ModPasswordRequest>{
privatestaticfinalintREQ_MODPASSWORD=0;
privatestaticfinalintINTF=1;
privatestaticfinalintAPMGT=2;publicvoidinit(){
messageHeader=newMessageHeader();
messageContent=newModPasswordRequest();
messageHeader.setType(REQ_MODPASSWORD);
messageHeader.setSender(INTF);
messageHeader.setReceiver(APMGT);
messageContent.setNewPassword("123456");
messageContent.setOldPassword("654321");
}
}最后是测试类Main.java
Copycode
publicclassMain{publicstaticvoidmain(finalString[]args)throwsException{
PropertyConfigurator.configure("log4j.properties");
AbstractApplicationContextctx=newClassPathXmlApplicationContext(newString[]{"spring-jms.xml"});
//ctx.registerShutdownHook();
IApmgtMessageProducerproducer=(IApmgtMessageProducer)ctx.getBean("producer");
ApmgtModPasswordRequestmessageData=newApmgtModPasswordRequest();
messageData.setMessageHeader(newMessageHeader());
messageData.setMessageContent(newModPasswordRequest());
messageData.init();
producer.sendMessage(messageData);
}
}还有两个配置文件,第一个spring-jms.xml
Copycode
<?
xmlversion="1.0"encoding="UTF-8"?
>
<