关于JMS与SPRING的整合实例(基于Apache ActiveMQ)

什么是JMS?

jms即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。

JMS的优势

当前,CORBA、DCOM、RMI等RPC中间件技术已广泛应用于各个领域。但是面对规模和复杂度都越来越高的分布式系统,这些技术也显示出其局限性:

(1)同步通信:客户发出调用后,必须等待服务对象完成处理并返回结果后才能继续执行;

(2)客户和服务对象的生命周期紧密耦合:客户进程和服务对象进程 都必须正常运行;如果由于服务对象崩溃或者网络故障导致客户的请求不可达,客户会接收到异常;

(3)点对点通信:客户的一次调用只发送给某个单独的目标对 象。
面向消息的中间件(Message Oriented Middleware,MOM)较好的解决了以上问题。发送者将消息发送给消息服务器,消息服务器将消息存放在若干队列中,在合适的时候再将消息转发给接 收者。这种模式下,发送和接收是异步的,发送者无需等待;二者的生命周期未必相同:发送消息的时候接收者不一定运行,接收消息的时候发送者也不一定运行; 一对多通信:对于一个消息可以有多个接收者。
已有的MOM系统包括IBM的MQSeries、Microsoft的MSMQ和BEA的MessageQ等。由于没有一个通用的标准,这些系统很难实现 互操作和无缝连接。

Java Message Service(JMS)是SUN提出的旨在统一各种MOM系统接口的规范,它包含点对点(Point to Point,PTP)和发布/订阅(Publish/Subscribe,pub/sub)两种消息模型,提供可靠消息传输、事务和消息过滤等机制。JMS并不是一个产品而是一个规范,JMS的出现是一个巨大变革。

满足大量应用的需求,运行于多种硬件和操作系统平台,支持分布式计算,支持标准接口和协议。开发人员通过调用中间件提供的大量API,实现异构环境的通信,从而屏蔽异构系统中复杂的操作系统和网络协议。

由于标准接口对于可移植性和标准协议对于互操作性的重要性,中间件已成为许多标准化工作的主要部分。分布式应用软件借助中间件可以在不同的技术之间共享资源。

总的来说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少了程序设计的复杂性,将注意力集中与自己的业务上,不必再为程序在不同软件系统上的移植而重复工作,从而大大减少了技术上的负担。

Take in Action

在理解了什么是JMS后,在实践阶段Dreamforce会向你介绍在Spring中整合JMS,同时结合Apache ActiveMQ来实现一个模拟聊天器的功能。

来务场景: A在输入端输入相应消息,消息会异步发送到ActiveMQ,B端会监听这个队列,如果有新数据入队,则接收此消息。

根据本实例,你可以通过简单的修改实现双人或多人自由聊天功能。

在本例中,使用Apache 的ActiveMQ来作为JMS中间件,这是一款相当成熟且开源的产品,得到了许多业内人士的好评。

开发采用Spirng Maven集成开发环境,所有的Jar包通过Maven进行管理 , 如果对Spring Maven集成开发环境配置不熟悉的,可以先看这里:http://dreamforce.me/archives/87

新建一个ApplicationContext-JMS.xml

定义JMS连接工厂

1
2
3
< bean id = "jmsFactory" class = "org.apache.activemq.ActiveMQConnectionFactory" >
< property name = "brokerURL" value = "tcp://localhost:61616" />
</ bean >

定义JMS Template

1
2
3
< bean id = "jmsTemplate" class = "org.springframework.jms.core.JmsTemplate" >
< property name = "connectionFactory" ref = "jmsFactory" />
</ bean >

定义消息目的地

1
2
3
< bean id = "dreamDestination" class = "org.apache.activemq.command.ActiveMQQueue" >
< constructor-arg index = "0" value = "dream.force" />
</ bean >

定义接收监听器

1
2
< bean id = "myTextListener" class = "com.darcy.jms.TextListener" >
</ bean >

定义一个JMS话题

1
2
3
4
< bean id = "jmsTopic" class = "org.apache.activemq.command.ActiveMQTopic"
autowire = "constructor" >
< constructor-arg value = "STOCKS.Dreamforce.jms" />
</ bean >

定义消费者(接收端)

1
2
3
4
5
6
< bean id = "javaConsumer"
class = "org.springframework.jms.listener.DefaultMessageListenerContainer" >
< property name = "connectionFactory" ref = "jmsFactory" />
< property name = "destination" ref = "chartDestination" />
< property name = "messageListener" ref = "myTextListener" />
</ bean >

定义发布者

1
2
3
4
5
6
< bean id = "publisher" class = "com.darcy.jms.SpringPublish" >
< property name = "template" >
< ref local = "jmsTemplate" />
</ property >
< property name = "destinations" ref = "chartDestination" />
</ bean >

JAVA核心代码一般由三个部分组成: 监听器(Listener),发布端(Publisher), 消息生产者(Creator)

监听器

 
package com.darcy.jms;
import java.util.Date;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.apache.activemq.command.ActiveMQMapMessage;
public class TextListener implements MessageListener{
public void onMessage(Message message) {
ActiveMQMapMessage msg = null ;
System.out.println( "ONMessage-----------------" +message.toString());
try {
if (message instanceof ActiveMQMapMessage) {
msg = (ActiveMQMapMessage) message;
String sentDate = msg.getString( "date" );
String reMessage = msg.getString( "message" );
int sentCount = msg.getInt( "count" );
System.out.println( "-------------New Message Arrival-----------" + new Date());
System.out.println( "It's " +sentCount+ " time From Darcy: " +reMessage+ " ---Send time :" + sentDate);
}
} catch (JMSException e) {
System.out.println( "JMSException in onMessage(): " + e.toString());
} catch (Throwable t) {
System.out.println( "Exception in onMessage():" + t.getMessage());
}
}
}

发布端

 
package com.darcy.jms;
import java.util.HashMap;
import java.util.Scanner;
import javax.jms.Destination;
import org.springframework.jms.core.JmsTemplate;
public class SpringPublish {
private JmsTemplate template;
private Destination[] destinations;
public void chart()
{
boolean chart = true ;
int count = 0 ;
while (chart)
{
count ++;
Scanner cin= new Scanner(System.in);
System.out.println( "输入聊天内容,输入N停止聊天" );
String text=cin.nextLine();
if (text.equals( "N" ))
{
chart = false ;
}
System.out.println( "我:" +text);
sendChartMessage(count,text);
}
}
protected void sendChartMessage( int count , String strMessage)
{
MyMessageCreator creator = new MyMessageCreator(count,strMessage);
template.send(destinations[ 0 ], creator);
}
public JmsTemplate getTemplate() {
return template;
}
public void setTemplate(JmsTemplate template) {
this .template = template;
}
public Destination[] getDestinations() {
return destinations;
}
public void setDestinations(Destination[] destinations) {
this .destinations = destinations;
}
}

消息生产者

 
package com.darcy.jms;
import java.util.Date;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
public class MyMessageCreator implements MessageCreator {
private int msgNo;
private String strMessage;
public MyMessageCreator( int no,String paramMessage) {
this .msgNo = no;
this .strMessage = paramMessage;
}
public Message createMessage(Session session) throws JMSException {
MapMessage message = session.createMapMessage();
message.setString( "date" , new Date().toString());
message.setString( "message" , strMessage);
message.setInt( "count" , msgNo);
return message;
}
}

完成上述的代码,聊天器的功能已经实现了,现在开始写一个TestCase来运行以上的代码

本例的TestCase用例是基于Spring的集成测试环境,同时你要保证将applicationContext-jms.xml纳入Spring的管理。

如果还不清楚如何搭建Spring集成测试环境的童鞋,请移步到这里 搭建Spring集成测试环境

 
package test.JSM;
import com.darcy.common.BaseTestCase;
import com.darcy.jms.SpringPublish;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
public class SpringJmsTestMain extends BaseTestCase{
private SpringPublish publisher;
private DefaultMessageListenerContainer javaConsumer;
public SpringPublish getPublisher() {
return publisher;
}
public void setPublisher(SpringPublish publisher) {
this .publisher = publisher;
}
public void testJMS()
{
javaConsumer.start();
publisher.chart();
}
public void setJavaConsumer(DefaultMessageListenerContainer javaConsumer) {
this .javaConsumer = javaConsumer;
}
public DefaultMessageListenerContainer getJavaConsumer() {
return javaConsumer;
}
}

至此代码书写已经完成。但是在运行之前我们需要启动Apache ActionMQ,以使JAVA端能访问到JMS组件。

下载地址:http://activemq.apache.org/download.html

解压后,进入Conf目录,打开ActiveMQ.xml编辑

1
2
3
< transportConnectors >
< transportConnector name = "openwire" uri = "tcp://localhost:61616" />
</ transportConnectors >

上面的代码是JMS通信地址,这里需要和Spring配置地址一致

启动ActionMQ, 运行bin目录里的ActionMQ.bat.

同时你也可以进入WEB Console, 默认访问地址为:http://localhost:8161/admin/

activeMQ console

运行TestCase,开始聊天吧~~~嘿嘿,不可上面的代码只支持单人聊天模式,接受端只是从JMS获取消息并输出。

附录:

Maven相关Denpendency(JMS)

1
2
3
4
5
6
7
8
9
10
11
< dependency >
< groupId >org.springframework</ groupId >
< artifactId >spring-jms</ artifactId >
< version >3.1.1.RELEASE</ version >
</ dependency >
< dependency >
< groupId >org.apache.geronimo.specs</ groupId >
< artifactId >geronimo-jms_1.1_spec</ artifactId >
< version >1.1</ version >
</ dependency >

由于各种原因,javax.jms包不能从maven默认的repository上下载,所以请使用这个dependency,当然jboss也提供了这个jms包的下载,请自由选择。

基于Java通讯开发jms源代码 (jms通讯开发源码) java,net,socket,通讯开发,jms /* * @(#)Message.java 1.60 02/04/09 * * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved. * * SUN PROPRIETARY/CONFIDENTIAL. * This software is the proprietary information of Sun Microsystems, Inc. * Use is subject to license terms. * */ import java.util.Enumeration; public interface Message { String getJMSMessageID() throws JMSException; void setJMSMessageID(String id) throws JMSException; long getJMSTimestamp() throws JMSException; void setJMSTimestamp(long timestamp) throws JMSException; byte [] getJMSCorrelationIDAsBytes() throws JMSException; void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException; String getJMSCorrelationID() throws JMSException; Destination getJMSReplyTo() throws JMSException; void setJMSReplyTo(Destination replyTo) throws JMSException; Destination getJMSDestination() throws JMSException; void setJMSDestination(Destination destination) throws JMSException; int getJMSDeliveryMode() throws JMSException; void setJMSDeliveryMode(int deliveryMode) throws JMSException; boolean getJMSRedelivered() throws JMSException; void setJMSRedelivered(boolean redelivered) throws JMSException; String getJMSType() throws JMSException; void setJMSType(String type) throws JMSException; long getJMSExpiration() throws JMSException; void setJMSExpiration(long expiration) throws JMSException; int getJMSPriority() throws JMSException; void setJMSPriority(int priority) throws JMSException; void clearProperties() throws JMSException; boolean propertyExists(String name) throws JMSException; boolean getBooleanProperty(String name) throws JMSException; byte getByteProperty(String name) throws JMSException; short getShortProperty(String name) throws JMSException; int getIntProperty(String name) throws JMSException; long getLongProperty(String name) throws JMSException; float getFloatProperty(String name) throws JMSException; double getDoubleProperty(String name) throws JMSException; String getStringProperty(String name) throws JMSException; Object getObjectProperty(String name) throws JMSException; Enumeration getPropertyNames() throws JMSException; void setBooleanProperty(String name, boolean value) throws JMSException; void setByteProperty(String name, byte value) throws JMSException; void setShortProperty(String name, short value) throws JMSException; void setIntProperty(String name, int value) throws JMSException; void setLongProperty(String name, long value) throws JMSException; void setFloatProperty(String name, float value) throws JMSException; void setDoubleProperty(String name, double value) throws JMSException; void setStringProperty(String name, String value) throws JMSException; void setObjectProperty(String name, Object value) throws JMSException; void acknowledge() throws JMSException; void clearBody() throws JMSException; } 通讯开发必备源码资料!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值