First, the service provider
Engineering battercake-provider, project structure as shown in FIG.
1.1 interface and implementation class to create a "selling pancakes" micro-services
package com.jp.service; public interface BatterCakeService { /** * Selling pancakes Service */ public String sellBatterCake(String name); }
package com.jp.service; import com.jp.service.BatterCakeService; /** * Selling pancakes Service implementation class * */ public class BatterCakeServiceImpl implements BatterCakeService { public String sellBatterCake (String name) { return name + "pancakes, selling particularly well" ; } }
1.2 RPC framework calls section
The section has two key components: RPC service provider and thread processing class
1) RPC service provider
- The need to publish the service is stored in a memory variable serviceList in. ( This example is to sell pancakes service instance object passed )
- Start socket, server.accept () method blocks there, listening input
- For each request, start a separate thread processing
. 1 Package com.jp.rpc; 2 . 3 Import the java.net.ServerSocket; . 4 Import the java.net.Socket; . 5 Import of java.util.ArrayList; . 6 Import java.util.Arrays; . 7 Import java.util.List; . 8 / ** 9 * RPC service provider 10 * 1, will need to publish service is stored in a memory variable serviceList 11 * 2, start socket, server.accept () method blocks there, listening input 12 * 3, for each a request to start processing a single thread 13 is * / 14 public class RpcProvider { 15 16 // store a registered service list 17 Private static List <Object> serviceList; 18 is . 19 / ** 20 is * rpc service release 21 is * @param Object provided (sold pancakes) service instance object 22 is * @param Port listening on port 23 is * @throws Exception 24 * / 25 public static void Export ( int Port, ... Object Services) throws Exception { 26 is serviceList = Arrays.asList (Services); 27 the ServerSocket Server = new newThe ServerSocket (Port); 28 the Socket Client = null ; 29 the while ( to true ) { 30 // block waiting for input, each will generate a request to a socket object 31 is Client = server.accept (); 32 // every request, processing starts a thread 33 is new new the thread ( new new ServerThread ( Client , serviceList )) start ();. 34 is } 35 } 36 }
2) Threading class
ServerThread ( Socke target , service instances list ) threading class code, ServerThread mainly to do the following steps
- Reads the service name sent by the client
- Determine whether the service is released
- If released, then take the logical reflection, dynamic invocation result is returned
- If you do not publish, notice the prompt return
1 package com.jp.rpc; 2 3 import java.io.IOException; 4 import java.io.ObjectInputStream; 5 import java.io.ObjectOutputStream; 6 import java.lang.reflect.Method; 7 import java.net.Socket; 8 import java.util.List; 9 10 public class ServerThread implements Runnable { 11 12 private Socket client = null; 13 14 private List<Object> serviceList = null; 15 16 public ServerThread(Socket client, List<Object> service) { 17 this.client = client; 18 this.serviceList = service; 19 } 20 21 //@Override 22 public void run() { 23 ObjectInputStream input = null; 24 ObjectOutputStream output = null; 25 try { 26 input = new ObjectInputStream(client.getInputStream()); 27 the Output = new new ObjectOutputStream (client.getOutputStream ()); 28 // reads the client to access the Service 29 Class serviceClass = (Class) input.readObject (); 30 // find the service class instance 31 Object obj = findService (serviceClass); 32 IF (obj == null ) { 33 is output.writeObject (serviceClass.getName () + "No service" ); 34 is } the else { 35 // using reflection to invoke the method, returns the result 36 @Get request from the request method name and method parameters; with the above-obtained service object instance; reflection method get specific examples; Invoke performed 37 [ the try{ 38 is String methodName =input.readUTF (); 39 <?> Class [] The parameterTypes = (<?> Class[]) input.readObject (); 40 Object [] = arguments(Object []) input.readObject (); 41 is 42 is Method, Method =. obj.getClass () getMethod (methodName, The parameterTypes); 43 is Object Result =Method.invoke (obj, arguments); 44 is output.writeObject (Result); 45 }the catch (Throwable t) { 46 output.writeObject(t); 47 } 48 } 49 } catch (Exception e) { 50 e.printStackTrace(); 51 } finally { 52 try { 53 client.close(); 54 input.close(); 55 output.close(); 56 } catch (IOException e) { 57 // TODO Auto-generated catch block 58 e.printStackTrace (); 59 } 60 } 61 is 62 is } 63 is 64 // to find the service instance of the service list 65 Private Object findService (serviceClass Class) { 66 for (Object obj: serviceList) { 67 Boolean isFather = serviceClass.isAssignableFrom ( obj.getClass ()); 68 IF (isFather) { 69 return obj; 70 } 71 is } 72 return null ; 73 is } 74 75 }
1.3 Publishing Service
. 1 Package com.jp.start; 2 . 3 Import com.jp.rpc.RpcProvider; . 4 Import com.jp.service.BatterCakeService; . 5 Import com.jp.service.BatterCakeServiceImpl; . 6 . 7 public class RpcBootStrap { . 8 public static void main (String [] args) throws Exception { 9 // instantiate "selling pancakes," the service implementation class 10 BatterCakeService batterCakeService = new new BatterCakeServiceImpl (); 11 // release service selling pancakes: 20006 registered in the port, and the provision of services examples of the incoming 12 RpcProvider.export(20006,batterCakeService); 13 } 14 }
Second, the service consumer
Consumers engineering battercake-consumer, project structure is shown below
2.1 rpc call part
Divided into two parts: a processor-based proxy (proxy class factory) and the service agent class object (i.e., the front plant returned)
1) proxy class processor (proxy class factory)
Responsible for the production proxy class ( incoming name service (class);? Ip; port )
1 package com.jp.rpc; 2 3 import java.lang.reflect.Proxy; 4 5 /** 6 * 用于生产服务代理类 7 */ 8 public class RpcConsumer { 9 public static <T> T getService(Class<T> clazz,String ip,int port) { 10 ProxyHandler proxyHandler =new ProxyHandler(ip,port); 11 return (T)Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class<?>[] {clazz}, proxyHandler); 12 } 13 }
2)服务代理类的处理器(该类就是代理类功能的具体实现者,其实就是封装了调用远程服务的过程(封装请求数据发给远端服务提供者,把提供者返回的结果返回))
- 建立socket连接
- 封装请求数据,发送给服务提供者
- 返回结果
1 package com.jp.rpc; 2 3 import java.io.ObjectInputStream; 4 import java.io.ObjectOutputStream; 5 import java.lang.reflect.InvocationHandler; 6 import java.lang.reflect.Method; 7 import java.net.Socket; 8 9 public class ProxyHandler implements InvocationHandler { 10 11 private String ip; 12 private int port; 13 14 public ProxyHandler(String ip, int port) { 15 this.ip = ip; 16 this.port = port; 17 } 18 19 //@Override 20 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 21 Socket socket = new Socket(this.ip, this.port); 22 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 23 ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 24 try { 25 output.writeObject(proxy.getClass().getInterfaces()[0]); 26 output.writeUTF(method.getName()); 27 output.writeObject(method.getParameterTypes()); 28 output.writeObject(args); 29 output.flush(); 30 Object result = input.readObject(); 31 if (result instanceof Throwable) { 32 throw (Throwable) result; 33 } 34 return result; 35 } finally { 36 socket.shutdownOutput(); 37 } 38 } 39 40 }
2.2 接下来建立一个测试类RpcTest如下
(跑该测试类前,记得运行在battercake-provider端的RpcBootstrap类发布BatterCakeService服务)
1 package com.jp.start; 2 3 import com.jp.rpc.RpcConsumer; 4 import com.jp.service.BatterCakeService; 5 6 public class RpcTest { 7 public static void main(String[] args) { 8 //生成代理类,三个参数:被代理对象,ip,端口 9 BatterCakeService batterCakeService = RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006); 10 //调用代理类的方法并获得结果 11 String result = batterCakeService.sellBatterCake("双蛋"); 12 System.out.println(result); 13 } 14 }
输出结果如下
https://blog.csdn.net/wangyunpeng0319/article/details/78651998
https://www.cnblogs.com/rjzheng/category/1205773.html