1. What is proxy mode?
As the name suggests, a proxy is a third party. For example, if a celebrity broker is responsible for handling all matters of a star, the agent will naturally find a way to do so by telling the agent what to do, after that, you can tell the stars the result.
This is a direct interaction between the caller and the called. Now, the caller and the called are separated, and the agent is responsible for transmitting information to complete the call.
Ii. What is the proxy mode used?
The proxy mode is a large mode, so it is widely used and can be seen from the agent type:
Remote Proxy: One of the most classic proxy modes, remote proxy is responsible for communicating with remote JVM to achieve normal interaction between local callers and remote callers
Virtual Proxy: Used to replace a large object and ensure that it is created only when necessary.
Protection Proxy: Provides access control to the caller and confirms the caller's permissions.
In addition, firewall proxy, intelligent reference proxy, cache proxy, synchronization proxy, complex hidden proxy, and copy proxy upon writing all have their own special purposes.
P.s. remote proxy is the most basic proxy mode, so it is necessary to discuss it separately. So this article will explain it in detail, and the rest of the proxies will be detailed in the supplementary blog
Iii. remote proxy
Some things can be easily solved without proxy, but some things must be done by proxy. For example, to call a method on another machine, we may have to use a proxy.
The internal mechanism of remote proxy is as follows:
To explain, Stub is a "pile", which is also called a "stub", representing the server object.
Skeleton is a "skeleton" (I don't know why it's "pile" or "skeleton", but I don't need to know it), which represents the client
Stub is clearly on the customer's side. Why is it not the customer's proxy but the service's proxy? Because the customer wants to interact with the server, and the service cannot interact in the remote JVM, Stub is used to represent the server. Calling stub is equivalent to calling the server (the internal communication mechanism is transparent to the client, for the client, there is no difference between calling stub and directly calling the server, which is one of the advantages of the proxy Mode)
The specific process is as follows:
- The client sends a method call request to stub (the client assumes that stub is a server)
- Stub receives a request and uses the socket to communicate with the server's skeleton to send the call request to skeleton.
- Skeleton receives the request and calls the local server (it sounds a bit strange, here the server is equivalent to the Service)
- The server performs the corresponding action and returns the result to the caller skeleton.
- Skeleton sends the result to stub through socket.
- Stub passes the result to the client
P.s. both steps 1 and 2 need to communicate through socket. Everything that passes each other must be serialized before sending and deserialized after receiving, this explains why the public method return values in server must be serializable.
Iv. remote proxy implementation
There are two ways to implement remote proxy:
- Custom stub and skeleton (implement internal communication)
- Using Remote Method Invocation (RMI) supported by Java can save a lot of trouble, but it is not easy to understand the internal principle.
First, let's give an example of a self-defined method. If there is a blog post about this very well, I recorded the link without authorization. Click here to jump>
The original text provides a complete example, so I will not go into details here. I will add a pseudo-class diagram to the original text for ease of understanding:
(Don't ask me why the class image is so painted. It's a "pseudo" class image ..)
Taking a closer look at the original text, it is not difficult to understand the remote proxy. stub and skeleton are responsible for communication, similar to the chat program written using Socket. In addition, there is nothing special
-------
The following describes how to use the RMI supported by Java to implement the proxy mode, so that you can clearly feel that many details are hidden.
First, define the remote interface:
Package proxypattern; import Java. RMI. remoteException;/*** defines the Service Interface (extended from Java. RMI. remote interface) * @ author ayqy */public interface service extends Java. RMI. remote {/* 1. method return type must be serializable * 2. every method must declare the exception throws RemoteException (because it is the RMI method) ** // *** @ return complete greeting statement * @ throws RemoteException */Public String greet (string name) throws RemoteException ;}
Note: The return type of the public method in the service interface must be serializable (in other words, the custom return type must implement the serializable Interface), while the string type has implemented the serializable interface.
Why do we need to define such an interface that extends from Java. RMI. Remote? The API documentation provides a clear explanation:
TheRemoteInterface serves to identify interfaces whose methods may be invoked from a non-local virtual machine. any object that is a remote object must directly or indirectly implement this interface. only those methods specified in a "remote interface", an interface that extendsjava.rmi.RemoteAre available remotely.
To put it bluntly, we want to tell the compiler that our service object can be called remotely.
-------
After defining the remote interface, you also need a specific implementation:
Package proxypattern; import Java. RMI. remoteException; import Java. RMI. server. unicastremoteobject;/*** remote service (extended from unicastremoteobject and implemented custom remote interface) * @ author ayqy */public class myservice extends unicastremoteobject implements Service {/*** is used to verify the program version (the acceptor will verify the uid in deserialization, causing an exception if it does not match) */Private Static final long serialversionuid = 1l;/*** empty constructor, just to declare an exception (the default constructor does not declare an exception) * @ throws RemoteException */protected myservice () throws RemoteException {}@ overridepublic string greet (string name) throws RemoteException {return "hey," + name ;}}
P.s. Services inherit the unicastremoteobject class to automatically generate the stub class (unicastremoteobject encapsulates the specific generation details, which saves the workload of A Class)
-------
It is not enough for the server to have services. We need a server to help us start the RMI Registration Service and register remote objects for the client to call:
Package proxypattern; import java.net. malformedurlexception; import Java. RMI. naming; import Java. RMI. remoteException; import Java. RMI. registry. locateregistry;/*** implements the server class, which is responsible for enabling the Service and registering the service object * @ author ayqy */public class server {public static void main (string [] ARGs) {try {// start the RMI registration service. The specified port is 1099 (1099 is the default port) locateregistry. createregistry (1099); // create the service object myservice service = new myservice (); // register the service on the RMI registration server and name it myservicenaming. rebind ("myservice", service);} catch (RemoteException e) {// todo auto-generated catch blocke. printstacktrace ();} catch (malformedurlexception e) {// todo auto-generated catch blocke. printstacktrace ();}}}
Note: Besides using locateregistry. createregistry () to enable the service, you can also use the command line (rmiregistry command) to enable the Service.
The server code is completed here. Just like the socket chat program, we need to write two parts of code: server and client.
-------
The implementation of the client is very simple, just like a test class:
Package proxypattern;/* References: * 1. java RMI how to use * http://blog.csdn.net/afterrain/article/details/1819659 * 2. RMI internal principle * http://www.cnblogs.com/yin-jingyu/archive/2012/06/14/2549361.html **/import Java. RMI. naming; /*** implement the customer class ** @ author ayqy */public class client {/*** to find the remote object and call the Remote Method */public static void main (string [] argv) {try {// if you want to find the myservice object from another machine that has started the RMI Registration Service, modify the IP address to make service = (service) naming. lookup ("// 127.0.0.1: 1099/myservice"); // call the remote method system. out. println (service. greet ("smilestone");} catch (exception e) {system. out. println ("client exception:" + E );}}}
P.s. we use naming directly. lookup () to get the stub object (yes, it's Stub. The real object is still on another machine, but of course it cannot be obtained. Here we get the service's Stub proxy ), call the proxy method to obtain the result.
Note the following details:
// If you want to find the myservice object from another machine that has started the RMI registration service, you can modify the IP address of service = (service) naming. lookup ("/// 127.0.0.1: 1099/myservice ");
Although it is only one sentence, two details are hidden:
- The client must know the service interface service. Because it is in the same local package, you do not need to worry about it. In a real application, the client and server are separated, therefore, the client needs to obtain a copy of the service interface, otherwise it cannot call
- The client must know the IP address and port number of the server)
-------
I have been busy for a long time. Check the running result (first run the server and then run the client ):
P.s. Use the RMI supported by Java to implement remote proxy. The reference document is a blog post by others, which explains in more detail.
P.s. it is too troublesome to start the RMI registration service using the command line method, and it must be a stub class. We do not recommend this method. The detailed operation details are also described in the above link blog, no more details
Note: No custom stub and skeleton classes are available until we see the test results? Yes, they do. They are hidden by RMI (it is said that skeleton is missing in RMI after java1.5, and even stub is missing in a later version .. But it does not matter. We know the original remote proxy)
V. Summary
Go back and think about what the remote proxy has done:
- Intercept and control method calls (this is also the most typical proxy mode, firewall proxy ..)
- The existence of remote objects is transparent to the customer (the customer treats the stub proxy object as a remote object completely, although the customer is somewhat curious about why exceptions may occur ..)
- Remote proxy hides communication details
When we need to call the method of the specified object on another Machine (JVM), using remote proxy is a good choice ..
Proxy pattern _ remote proxy Parsing