RMI is introduced
Remote Method Invocation (RMI) model is a distributed object Invocation. RMI enables an object in one JVM to call an object Method in another JVM and get the Invocation result. The other JVM here could be on the same machine or it could be a remote machine. Therefore, RMI means that you need a Server and a Client.
The Server side typically creates an object and makes it accessible remotely.
- This object is called a remote object.
- The Server needs to register this object for remote access by clients.
The Client invokes methods on objects that can be accessed remotely, and the Client communicates with the Server and passes information to each other.
At this point, do you find it convenient to use RMI to build distributed applications, which can communicate with each other just like RPC, and even very similar to the idea of microservices today?
How RMI works
Before writing RMI code, it is necessary to understand how RMI works. How does the Client and Server communicate in RMI?
The following figure helps us understand the RMI workflow.
As you can see from the figure, the Client has a Stub, which is sometimes called a Stub. It is the proxy object of the RMI Client. The Stub is used to construct an information block when requesting a remote method, and the RMI protocol sends this information block to the Server.
This information block consists of several parts:
- Remote object identifier.
- Method description of the call.
- The marshalled parameter value (object serialization is used in RMI protocol).
Since the Client has a Stub that constructs a block of information and sends it to the Server, the Server must have a Skeleton that receives the information quickly.
Its main work is:
- Call object identifiers and method descriptions in parsing information fast, and call specific object methods on the Server side.
- Gets the return value or outlier of the call.
- Group the returned value and return it to the client Stub.
At this point, the result of a call from Client to Server can be obtained.
Development of RMI
Through the above introduction, we know the concept of RMI and the working principle of RMI. The following describes the development process of RMI.
A scenario is shown here. Assume that the Client needs to query user information, and the user information exists on the Server. Therefore, the RMI protocol interface is opened on the Server for the Client to call the query.
RMI Server
The Server side mainly builds a class User that can be transferred, a class UserService that can be accessed remotely, and this object is registered with RMI for the client to use.
1. Define the server interface (needs to inherit from the Remote class and methods need to throw RemoteExceptions).
package com.wdbyte.rmi.server; import java.rmi.Remote; import java.rmi.RemoteException; /** * RMI Server * * @author www.wdbyte.com * @date 2021/05/08 */ public interface UserService extends Remote { /** * Query User * * @param userId * @return * @throws RemoteException */ User findUser(String userId) throws RemoteException; }Copy the code
The User object is defined in Step 3.
2. Implement the server interface (need to inherit UnicastRemoteObject class, implement the defined interface).
package com.wdbyte.rmi.server; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; /** * @author www.wdbyte.com * @date 2021/05/08 */ public class UserServiceImpl extends UnicastRemoteObject implements UserService { protected UserServiceImpl() throws RemoteException { } @Override public User findUser(String userId) Throws RemoteException {if ("00001". Equals (userId)) {User User = new User(); User. Elegantly-named setName (" jin yong "); user.setAge(100); User. SetSkill (" writing "); return user; } throw new RemoteException(" RemoteException "); }}Copy the code
3. Define the transfer object, which implements the Serializable interface.
Classes that need to be transferred must implement serialization interfaces, otherwise an error will be reported during transmission. A simple tutorial on how to generate serialVersionUID in IDEA is also attached at the end of the article.
package com.wdbyte.rmi.server; import java.io.Serializable; /** * * @author www.wdbyte.com * @date 2021/05/08 */ public class User implements Serializable { private static final long serialVersionUID = 6490921832856589236L; private String name; private Integer age; private String skill; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSkill() { return skill; } public void setSkill(String skill) { this.skill = skill; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", skill='" + skill + '\'' + '}'; }}Copy the code
4. Register (rMIRegistry) remote objects and start the server program.
The server is bound to the UserService object as the remote access object and is set to port 1900 at startup.
package com.wdbyte.rmi.server; import java.rmi.Naming; import java.rmi.registry.LocateRegistry; /** * RMI Server ** @author https://www.wdbyte.com * @date 2021/05/08 */ public class RmiServer {public static void main(String[] args) { try { UserService userService = new UserServiceImpl(); LocateRegistry.createRegistry(1900); Naming.rebind("rmi://localhost:1900/user", userService); System.out.println("start server,port is 1900"); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
RMI Client
Compared to the Server side, the Client side is much simpler. Directly introducing classes that are remotely accessible and need to be transported can make a call with the address bound to the port and Server side.
package com.wdbyte.rmi.client; import java.rmi.Naming; import com.wdbyte.rmi.server.User; import com.wdbyte.rmi.server.UserService; /** * @author https://www.wdbyte.com * @date 2021/05/08 */ public class RmiClient { public static void main(String args[]) { User answer; String userId = "00001"; try { // lookup method to find reference of remote object UserService access = (UserService)Naming.lookup("rmi://localhost:1900/user"); answer = access.findUser(userId); System.out.println("query:" + userId); System.out.println("result:" + answer); } catch (Exception ae) { System.out.println(ae); }}}Copy the code
RMI test
Start the Server.
start server,port is 1900
Copy the code
Start the Client.
Query :00001 result:User{name=' kingyong ', age=100, skill=' writing '}Copy the code
If the Client passes in a non-existent userId.
java.rmi.ServerException: RemoteException occurred in server thread; Nested exception is: Java rmi remoteexceptions: no such personCopy the code
The generation of serialVersionUID
SerialVersionUID is generated in IDEA, open the setting, and check as shown in the following figure.
Select the class that you want to generate serialVersionUID and press the smart prompt shortcut key.