RMI远程方法调用

来源:互联网 发布:snmpv3 java 编辑:程序博客网 时间:2024/05/16 13:46

1、RMI 简介


Remote Method Invocation,远程方法调用,是一种技术,基于JRMP(Java Remote MessagingProtocol)协议

是Java分布式应用的基础,EJB的基石,构建于TCP之上的应用层协议,仅仅适用于java语言编写的应用程序之间通讯。

在RMI协议中,对象使用序列化机制编码。


2、RMI 开发示例

  • 定义远程服务接口:必须继承 Remote 接口
  • 定义远程服务实现类:必须继承 UnicastRemoteObject 类
  • 注册RMI服务
  • 客户端使用RMI服务

2.1 定义远程服务接口

package com.yli.rmi.server;import java.rmi.Remote;import java.rmi.RemoteException;import java.util.Map;/** * 定义远程服务对象接口 UserService,必须继承  , 方法需要抛出 RemoteException异常<br> * 1.方法抛出异常是为了客户端能捕获异常<br> * 2.客户端需要定义一模一样的接口,包结构也得一样<br> * 因此一般是服务方提供jar包给客户端调用,客户端不需要重新定义业务接口 */public interface UserService extends Remote {    Map<String, Object> queryUser(String userId) throws RemoteException;}

2.2 定义远程服务实现类

package com.yli.rmi.server;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;import java.util.HashMap;import java.util.Map;/** * 定于远程服务实现类,必须继承UnicastRemoteObject <br> * 由于RMI协议传输数据是依靠对象的序列化机制<br> * 因此 UnicastRemoteObject 其顶层父类实现了Serializable接口<br> * 这就要求你定义的服务类也要给予序列化Id,在Eclipse工具里面可自动生成<br> * 也可以借助 jdk\bin\serialver.exe 工具来时限 */public class UserServiceImpl extends UnicastRemoteObject implements UserService {    protected UserServiceImpl() throws RemoteException {        super();    }    private static final long serialVersionUID = 6269131066149250252L;    @Override    public Map<String, Object> queryUser(String userId) throws RemoteException {        String request = String.format("----->服务端收到客户端请求:userId=%s,timestamp=%s", userId, System.currentTimeMillis());        System.out.println(request);                Map<String, Object> user = new HashMap<String, Object>();        user.put("userId", userId);        user.put("userName", "test");                return user;    }}

2.3 注册RMI服务

package com.yli.rmi.server;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.util.Hashtable;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;/** * 注册RMI服务 */public class RmiServiceRegister {    public static void main(String[] args) throws RemoteException, NamingException {        /**         * RMI 协议url格式 rmi://host[:port]/serviceName <br>         * 比如注册一个服务:rmi://abc.com/queryUserInfo <br>         * 如果在本机测试,比如使用:rmi://localhost:1099/queryUserInfo <br>         */        bind1();        // bind2();    }    public static void bind1() throws RemoteException, NamingException {        System.out.println("**** beging register queryUserService ****");        int port = 8888;        String rmiUrl = "rmi://localhost:" + port + "/queryUserService";        // 注册RMI服务方监听端口        LocateRegistry.createRegistry(port);        // 绑定服务        UserServiceImpl uimpl = new UserServiceImpl();        Context namingCxt = new InitialContext();        namingCxt.bind(rmiUrl, uimpl);        // 重新绑定则会覆盖已经存在的服务        // namingCxt.rebind(rmiUrl, uimpl);        System.out.println("**** end register ****");    }    public static void bind2() throws RemoteException, NamingException {        System.out.println("**** beging register queryUserService ****");        // 设置上下文        Hashtable<String, String> env = new Hashtable<String, String>();        // 初始化上下文        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");        // 指定URL        int port = 8888;        env.put(Context.PROVIDER_URL, "rmi://localhost:" + port);        // 注册RMI        LocateRegistry.createRegistry(port);        // 绑定服务        UserServiceImpl uimpl = new UserServiceImpl();        Context context = new InitialContext(env);        // 通过hashtable已经把 url 初始化到Context了        // 此处只要绑定服务名称即可        context.bind("queryUserService", uimpl);        // 重新绑定则会覆盖已经存在的服务        // context.rebind("queryUserService", uimpl);        System.out.println("**** end register ****");    }}

2.4 客户端使用RMI服务

package com.yli.rmi.client;import java.rmi.RemoteException;import java.util.Map;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import com.yli.rmi.server.UserService;/** * RMI客户端测试 */public class TestRmiClient {    public static void main(String[] args) throws NamingException, RemoteException {        // RMI 服务地址        String rmiUrl = "rmi://localhost:8888/queryUserService";        Context namingCxt = new InitialContext();        // 查找远程RMI服务        UserService us = (UserService) namingCxt.lookup(rmiUrl);        Map<String, Object> user = us.queryUser("1001");        System.out.println(user);    }}



0 0