RMI远程方法调用

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值