最近在EJB开发中接触到JNDI和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
Java消息服务(Java Message Service,JMS)是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
1) 与具体平台无关, 绝大多数MOM提供商都对JMS提供支持
2) 两种消息模式 : 点对点(PTP)和 发布者/订阅者(Pub/Sub)
3) 支持同步和异步的消息处理
4) 支持面向事件的方法接收消息
三 JNDI
JNDI (Java Naming and Directory Interface,Java命名和目录服务接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI API的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
集群JNDI实现了高可靠性JNDI,通过服务器的集群,保证了JNDI的负载平衡和错误恢复。在全局共享的方式下,集群中的一个应用服务器保证本地JNDI树的独立性,并拥有全局的JNDI树。每个应用服务器在把部署的服务对象绑定到自己本地的JNDI树的同时,还绑定到一个共享的全局JNDI树,实现全局JNDI和自身JNDI的联系。
JNDI具有以下优点:
1) 包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务;
2) 可以同时连接到多个命名或目录服务上;
3) 建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必知道对象或资源的物理ID。
利用JNDI的命名与服务功能来满足企业级API对命名与服务的访问,诸如EJB、JMS、 JDBC 2.0以及IIOP上的RMI通过JNDI来使用CORBA的命名服务。
JNDI的用途:
1)可以用jndi来得到object类的属性
如:Attribute attr=directory.getAttributes(personName).get("email");
String email = (String)attr.get();
2)可以用jndi来搜索对象
如:M =directory.search("o=Wiz,c=US", "sn=TGB", controls);
查找谁的名字叫M在TGB部门的员工?
3)可以用jndi通过naming/directory服务查询像printers和databases的对象
如:查询 Printer
Printer printer =(Printer)namespace.lookup(printerName);
printer.print(document);
4)可以用jndi列表出命名空间的特殊级别的内容
如:NamingEnumeration list =namespace.list("o=Widget, c=US");
while (list.hasMore()) {
NameClassPair entry =(NameClassPair)list.next();
display(entry.getName(),entry.getClassName());
}
四 基于JMS和JNDI开发一个消息客户端应用的编程步骤:
1) 使用JNDI查找一个ConnectionFactory对象。
2) 使用JNDI查找一个或者多个Destination对象。
3) 使用ConnectionFactory创建一个JMS连接
4) 使用连接创建一个或者多个JMS Sessions
5) 使用Session and Destinations 创建所需的MessageProducers 和MessageConsumers
6) 告知Connection 开始传送消息
代码如下:
public class QueueMessageClient {
public static void main(String[] args)throws Exception {
InitialContext context = newInitialContext();
//获取QueueConnectionFactory对象
QueueConnectionFactoryfactory=(QueueConnectionFactory)context.lookup("ConnectionFactory");
//创建QueueConnection
QueueConnectionconnection=factory.createQueueConnection();
//创建QueueSession对象
QueueSessionsession=connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//获取Destination对象
Queue queue =(Queue)context.lookup("queue/myqueue");
//创建文本消息
TextMessagemsg=session.createTextMessage("Hello World --世界,你好");
//创建发送者
QueueSendersender=session.createSender(queue);
//发送消息
sender.send(msg);
//关闭会话
session.close();
connection.close();
System.out.println("消息已发送");
}
}