下午和莉莉讨论JNDI,感觉网上好多资料都写到太过于高深莫测了,具体了解了之后,发现JNDI的使用目的,最根本的就是java应用通过一个名字获取其他JVM中的数据。而在提供JNDI服务的服务端应用中,建立了一个类似键值对的形式,存储JNDI的名字和数据的绑定。这就类似于数据库的连接池,不必每次去连接数据库都重新建立一个连接,而是直接从连接池中获取已有连接拿来使用即可,节省了内存同时也优化了效率。
网上大多数文章都是在讨论J2EE中如何使用JNDI获取数据源,确实很方便,但是作为理解JNDI的实例,稍显麻烦,下面将通过一个RMI与JNDI的集成服务端和客户端简单分析下RMI的使用和JNDI的原理。
java version "1.7.0_40"
RMI服务端接口
package com.jxl.rmi.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiSimple extends Remote {
public String sayHello() throws RemoteException;
}
RMI服务端接口的实现
package com.jxl.rmi.server;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RmiSimpleImpl extends UnicastRemoteObject implements RmiSimple {
private static final long serialVersionUID = 1L;
protected RmiSimpleImpl() throws RemoteException {
super();
}
public String sayHello() throws RemoteException {
return "hello lili!!";
}
}
RMI服务的实现
package com.jxl.rmi.server;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class RmiJndiSever {
public static void main(String[] args) {
try {
//注册RMI服务器端口
LocateRegistry.createRegistry(8080);
//建立RMI服务端接口实现对象
RmiSimple server = new RmiSimpleImpl();
//设置JNDI属性
Properties properties = new Properties();
//RMI的JNDI工厂类
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY , "com.sun.jndi.rmi.registry.RegistryContextFactory");
//RMI服务端的访问地址
properties.setProperty(Context.PROVIDER_URL, "rmi://localhost:8080");
//根据JNDI属性,创建上下文
InitialContext ctx = new InitialContext(properties);
//将服务端接口实现对象与JNDI命名绑定,这个地方写的并不是很规范
//如果在J2EE开发中,规范的写法是,绑定的名字要以java:comp/env/开头
ctx.bind("RmiSimple", server);
System.out.println("RMI与JNDI集成服务启动.等待客户端调用...");
} catch (RemoteException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
RMI客户端的实现,使用JNDI去查找并调用RMI方法
package com.jxl.rmi.client;
import java.rmi.RemoteException;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.jxl.rmi.server.RmiSimple;
public class JndiRmiClient {
public static void main(String[] args) {
//设置JNDI属性
Properties properties = new Properties();
//RMI的JNDI工厂类
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY , "com.sun.jndi.rmi.registry.RegistryContextFactory");
//RMI服务端的访问地址
properties.setProperty(Context.PROVIDER_URL, "rmi://localhost:8080");
try {
//根据JNDI属性,创建上下文
InitialContext ctx = new InitialContext(properties);
//根据JNDI上下文,查找并获取到远程的RMI对象
RmiSimple remote = (RmiSimple) ctx.lookup("RmiSimple");
System.out.println(remote.sayHello());
} catch (NamingException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
服务端运行时,会建立一个监听,等待客户端的命令,运行结果:
RMI与JNDI集成服务启动.等待客户端调用...
客户端运行时,会成功调用到服务端的方法,并进行打印输出:
hello lili!!
以上如果有理解错误,请各位不吝批评指正!
参考:RMI 与 JNDI集成 http://bbs.csdn.net/topics/340060074
参考:对java:comp/env的研究 http://f543711700.iteye.com/blog/1173618