I wrote an implementation case of Java RMI (Remote Method Call)

Python WeChat Subscription Applet Course Video

https://edu.csdn.net/course/detail/36074

Python Actual Quantitative Transaction Finance System

https://edu.csdn.net/course/detail/35475
I wrote a simple implementation case of Java RMI (Remote Method Call).

To better understand RMI (remote method calls), the meaning of serialization, and so on, it took more than three days for the liver to implement a Java RMI.

!!! High-energy alert!!!

Code is a bit heavy, attached a sketch to understand

The whole process is divided into two steps

  • Step 1 - Registration process: The client obtains the remote client object specified by the registry through the specified route;
  • Part 2 - Service Call Procedure: Clients access remote servers (proxy services) through remote client objects to access the implementation of real services

Adjust to a comfortable position and take your time...Say less, code!!!

1. Define Remote Tag Interface

Interface-oriented programming, depending on how the code behind uses it

//Tag interface: Implementing MyRMI interface directly or indirectly will gain the ability to make remote calls
public interface MyRMI{
}

2. Write RMI Service Registry

Registry class: used to register and obtain services, the core is hashMap routing table object

/**
 * Registry: Maintain the registry for service publishing
 */
public class MyRMIRegistry {
    //Default port
    public final int REGISTRY\_PORT = 10099;
    private String host;
    private int port;
    private Map bindings;

    public MyRMIRegistry(int port){
        this.port = port;
    }
    public MyRMIRegistry(String host, int port){
        this.host=host;
        this.port=port;
    }

    public void createRegistry(String serverName,MyRMI myRMI){
        //Register the service and start the service
        this.bindings = new HashMap<>();
        String host = null;
        try {
            host = Inet4Address.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        //Routing rules can be customized as long as the Key is unique
        String binding = "myrmi://"+host+":"+port+"/"+serverName;
        this.bindings.put("myrmi://"+host+":"+port+"/"+serverName,myRMI);
        System.out.println("Registered services are:"+bindings.keySet().toString());
        MyRMIRegistryServer myRMIRegistryServer = new MyRMIRegistryServer(this.port, this.bindings);
        Executors.newCachedThreadPool().submit(myRMIRegistryServer); //Thread pool startup service

    }

    public MyRMI getRegistry(String serverName){
        Socket socket = null;
        ObjectOutputStream out = null;
        ObjectInputStream in = null;
        MyRMI myRMI = null;
        //Pass
        try {
            socket = new Socket(host, port);
            out = new ObjectOutputStream(socket.getOutputStream());
            out.writeObject("myrmi://"+host+":"+port+"/"+serverName);
            in = new ObjectInputStream(socket.getInputStream());
            myRMI = (MyRMI)in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return myRMI;
    }
}

Threads for RMI registry to get services: Start registry services and wait for clients to get remote clients in the routing table

/**
 * RMI Registry Get Service Threads
 */
public class MyRMIRegistryServer implements Runnable {
    private int port;
    private Map bindings;
    public MyRMIRegistryServer(Integer port,Map bindings){
        this.port = port;
        this.bindings = bindings;
    }

    @Override
    public void run() {
        ServerSocket serverSocket = null;
        ObjectOutputStream out = null;
        ObjectInputStream in = null;
        try {
            serverSocket = new ServerSocket(this.port);
            while(true){
                Socket socket = serverSocket.accept();
                in = new ObjectInputStream(socket.getInputStream());
                out = new ObjectOutputStream(socket.getOutputStream());
                //See what services clients want
                String serverName = (String)in.readObject();
                Iterator iterator = bindings.keySet().iterator();
                while (iterator.hasNext()){
                    String key = (String) iterator.next();
                    if(serverName.equals(key)){
                        //Respond to client service object
                        MyRMI myRMI = bindings.get(key);
                        out.writeObject(myRMI);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            //Enter after exception
            try {
                if (out!=null)  out.close();
                if (in!=null)   in.close();
                if (serverSocket!=null) serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

3. Define the service interface to be published

An interface that provides RMI services must inherit a custom MyRMI tag interface

/**
 * Service Interface
 */
public interface Hello extends MyRMI {
    public String sayHello(String name);
}

4. Entity classes used by services

/**
 * Object Data Class: Person
 */
public class Person implements Serializable {
    //Serialized version UID
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String sex;

    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;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "Person{" + "name='" + name + ", age=" + age + ", sex='" + sex + '}';
    }
    public Person() {
    }
    public Person(String name, Integer age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}

5. Implement the service interface to be published

/**
 * External Service Implementation
 */
public class HelloImpl implements Hello {
    private static File file = new File("D:/HelloRMI.txt");
    private static List list = new ArrayList<>();

    @Override
    public String sayHello(String name) {
        String result = "Not Get"+name+"Information";
        try {
            List personList = readList();
            for(Person person:personList){
                if (person.getName().equals(name)){
                    result = "Hello , welcome to the RMI! "
                            + "Full name:"+name + " Age:"+person.getAge()+" Gender:"+person.getSex();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * Generate data to prepare for testing
     * @param args
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //Data preparation: Collection classes all implement serialization interface Serializable
        list.add(new Person("Zhang San", 38, "male"));
        list.add(new Person("Li Si", 38, "male"));
        list.add(new Person("Flowers like flowers", 18, "female"));
        //Persist Object Data
        writerList(list);
        //Query persisted object data
        List personList = readList();
        System.out.println("Traversing persistent object data>");
        for (Person person : personList) {
            System.out.println(person);
            if (person.getAge() == 38) {
                person.setAge(18);
            }
        }

    }

    public static void writerList(List list) throws IOException {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));
        objectOutputStream.writeObject(list);
        objectOutputStream.close();
    }

    public static List readList() throws IOException, ClassNotFoundException {
        //Read Normal File Deserialization
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
        List personList = (List) objectInputStream.readObject();
        objectInputStream.close();
        return personList;
    }
}

6. Thread classes for remote clients

Remote client class for auto-generating service interfaces (inheriting the MyRMI tag interface): This class was originally a generic class implementation, and for ease of implementation, the Hello interface was directly implemented

/**
 * Thread class generation for remote clients:
 *      For ease of implementation, this directly implements service interface writing
 */
public class HelloClientThread implements Hello,Serializable {
    //Serialized version UID
    private static final long serialVersionUID = 1L;
    private Map<String,Object> map = new HashMap<>(); //Message object: method name and parameter object
    private String ip;
    private int port;

    public HelloClientThread(String ip, int port){
        this.ip = ip;
        this.port = port;
    }

    @Override
    public String sayHello(String name) {
        map.put("sayHello",name);
        String result = (String)send();
        return result;
    }

    private Object send(){
        Object o =null;
        Socket socket = null;
        ObjectOutputStream out = null;
        ObjectInputStream in = null;
        try {
            socket = new Socket(ip, port);
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());
            //Tell the server what service I want to call
            out.writeObject(map);
            //Get service implementation objects
            o = in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                if (out!=null)  out.close();
                if (in!=null)   in.close();
                if (socket!=null) socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return o;
    }
}

7. Thread classes on remote servers

Remote server-side class for automatic generation of service interfaces (inheriting the MyRMI tag interface): This class is also a generic class implementation, and some code has not yet been decoupled for ease of implementation

/**
 * Generation of thread classes on remote servers:
 *      For ease of implementation, this implements the service thread class directly
 */
public class HelloServerThread implements Runnable {
    private Integer port;
    private MyRMI myRMI;
    public HelloServerThread(Integer port, MyRMI myRMI){
        this.port = port;
        this.myRMI = myRMI;
    }

    @Override
    public void run() {
        ServerSocket serverSocket = null;
        ObjectOutputStream out = null;
        ObjectInputStream in = null;
        try {
            serverSocket = new ServerSocket(this.port);
            while(true){
                Socket socket = serverSocket.accept();
                in = new ObjectInputStream(socket.getInputStream());
                out = new ObjectOutputStream(socket.getOutputStream());
                //See what services clients want
                Map map = (Map)in.readObject();
                Iterator iterator = map.keySet().iterator();
                while (iterator.hasNext()){
                    String key = (String) iterator.next();
                    if("sayHello".equals(key)){
                        //Respond to client service object
                        Hello hello = (Hello)myRMI;
                        String result = hello.sayHello((String) map.get(key));
                        out.writeObject(result);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            //Enter after exception
            try {
                if (out!=null)  out.close();
                if (in!=null)   in.close();
                if (serverSocket!=null) serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    
}

8. Classes generated and started by remote client and remote server

/**
 * Classes for remote client generation and remote server generation and startup
 */
public class RemoteSocketObject{
    //Default port
    private int port=18999;

    //Specify the remote communication port and proxy service
    public MyRMI createRemoteClient(MyRMI myRMI,int port){
        if (port > 0)
            this.port=port;

        MyRMI myRMIClient = null;
        try {
            //Generate the underlying communication server and start
            HelloServerThread helloServerThread = new HelloServerThread(this.port, myRMI);
            Executors.newCachedThreadPool().submit(helloServerThread); //Thread pool startup service
            //Generate underlying communication client
            String localHost = Inet4Address.getLocalHost().getHostAddress();
            System.out.println("host="+localHost+",port="+this.port);
            myRMIClient= new HelloClientThread(localHost, this.port);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return myRMIClient;
    }
    
}

9. Service Publishing Class

/**
 * RMI Service Publishing Class
 */
public class HelloServer {
    public static void main(String[] args) {

        System.out.println("Create Hello Remote Method Invocation...");
        //Instantiate a Hello
        Hello hello = new HelloImpl();
        //Convert to a remote service and provide remote clients
        Hello remoteClient = (Hello)new RemoteSocketObject().createRemoteClient(hello, 0);
        //Hosting the service implementation to the Socket service
        MyRMIRegistry myRMIRegistry = new MyRMIRegistry(16000);
        //Open Thread Service
        myRMIRegistry.createRegistry("Hello",remoteClient);

    }
}

10. Client Test Class

/**
 * Client Test Class
 *      Clients only know the service interface, the address of the service publication, and the name of the service publication
 */
public class TestHello {
    public static void main(String[] args) {
        //Note that it is not 127.0.0.1, do not know the host to see the information printed after the server side is started
        //Port 16000 is the registry port, the port client of the underlying proxy service does not need to know
        MyRMIRegistry client = new MyRMIRegistry("192.168.233.1", 16000);
        Hello hello = (Hello) client.getRegistry("Hello");
        System.out.println(hello.sayHello("Zhang San"));
    }
}

11. Summary

All the code comes together, in the real scene:

The client only knows: TestHello class, Hello interface definition, MyRMI tag interface, MyRMIRegistry registration class code (only Key is known in the routing table, no specific value is known);

The server only knows: Hello interface, HelloImpl service implementation class, MyRMI tag interface, MyRMIRegistry registration class code (Key and specific values are known in the routing table);

Other code implementations are insensitive. In order to simply implement remote clients and remote servers, service interfaces are coupled to both, and decoupling is not common.

Java Future Articles

Java Full Stack Learning Route, Learning Resources and Interview Questions

What is a good architect in my mind?

Download classic programming books for free

More Quality Articles and Resources 👇

Originality is not easy, triple support: share, praise, see 👇

Keywords: Go Back-end computer

Added by xfezz on Sat, 05 Mar 2022 19:32:59 +0200