使用回调函数的RMI简单实例

来源:互联网 发布:淘宝的专属推荐是什么 编辑:程序博客网 时间:2024/05/16 17:09

工程结构

  • src
    • client
      • TestClient.java
    • entity
      • PersonEntity.java
    • registry
      • ServerRegistry.java
    • service
      • PersonService.java
      • PersonServiceImpl.java
      • PrintPersonService.java
      • PrintPersonServiceImpl.java

实现

1. 创建数据Bean

   该bean用于在客户端与服务端之间传输数据。需要实现Serializable接口用于类对象的序列化与反序列化。

package entity;import java.io.Serializable;public class PersonEntity implements Serializable{    private static final long serialVersionUID = -6086743965334139076L;    private String name;    private int age;    public PersonEntity(String name, int age) {        super();        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

2. 创建服务端远程服务接口

   注意:远程方法必须抛出RemoteException。

   此方法用于实现服务端响应客户端查询人口列表。

package service;import java.rmi.Remote;import java.rmi.RemoteException;public interface PersonService extends Remote{    public void getPersons(PrintPersonService printService) throws RemoteException;}

3. 实现服务端远程服务

   服务端实现远程接口,供客户端调用。
   注意: 需要继承构造函数的实现。

package service;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;import java.util.ArrayList;import java.util.List;import entity.PersonEntity;public class PersonServiceImpl extends UnicastRemoteObject implements PersonService{    private static final long serialVersionUID = 621297838434573682L;    public PersonServiceImpl() throws RemoteException {        super();        // TODO Auto-generated constructor stub    }    /**    * 接收客户端的远程接口实例PrintPersonService    */    public void getPersons(PrintPersonService printService)            throws RemoteException {        System.out.println("Server thread get person");        try {            Thread.currentThread();            Thread.sleep(3000); //此处沉睡3秒用于模拟执行所需时间        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        List<PersonEntity> persons = new ArrayList<PersonEntity>();        persons.add(new PersonEntity("Bob", 11));        persons.add(new PersonEntity("Rose", 12));        printService.printPerson(persons); //执行客户端的回调函数    }}

4. Server注册、发布远程接口

   该类中的main方法用于启动服务端远程服务

package registry;import java.net.MalformedURLException;import java.rmi.AlreadyBoundException;import java.rmi.Naming;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import service.PersonService;import service.PersonServiceImpl;public class ServiceRegistry {    public static void main(String[] args) {//服务端程序入口        try {            PersonService personService = new PersonServiceImpl();            LocateRegistry.createRegistry(32479);            Naming.bind("rmi://127.0.0.1:32479/PersonService", personService);            System.out.println("Service started...");        } catch (RemoteException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (MalformedURLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (AlreadyBoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

5. Client远程接口

   客户端的回调函数也需要以远程接口的方式实现,供服务端调用。在调用回调函数的过程中,客户端与服务端的角色反转。

package service;import java.rmi.Remote;import java.rmi.RemoteException;import java.util.List;import entity.PersonEntity;public interface PrintPersonService extends Remote{    public void printPerson(List<PersonEntity> persons) throws RemoteException;}
package service;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;import java.util.List;import entity.PersonEntity;public class PrintPersonServiceImpl extends UnicastRemoteObject implements PrintPersonService{    private static final long serialVersionUID = 5471018647833463871L;    public PrintPersonServiceImpl() throws RemoteException {        super();        // TODO Auto-generated constructor stub    }    public void printPerson(List<PersonEntity> persons) {        System.out.println("Client thread print person!");        for (PersonEntity person : persons) {            System.out.println(person.getName()+" "+person.getAge());        }    }}

6. Client调用服务端远程接口

package client;import java.net.MalformedURLException;import java.rmi.Naming;import java.rmi.NotBoundException;import java.rmi.RemoteException;import service.PersonService;import service.PrintPersonServiceImpl;public class TestClient {    public static void main(String[] args) {//客户端程序入口        try {            PersonService personService = (PersonService)Naming.lookup("rmi://127.0.0.1:32479/PersonService");            personService.getPersons(new PrintPersonServiceImpl());//客户端调用服务端的远程函数,并将回调函数的远程接口实例传递给服务端,供服务端调用        } catch (MalformedURLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (RemoteException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (NotBoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

运行

   先运行服务端,后运行客户端,可观察到在客户端启动3秒之后,客户端标准输出Terminal输出了Person列表