以TCP方式简单实现RPC

1 篇文章 0 订阅
1 篇文章 0 订阅

RPC远程过程调用,可以采用TCP方式支持,也可采用HTTP方式进行支持(WebService也支持)。传值可选用JSON、XML或者二进制进行传递,此示例为了提高效率采用二进制流进行传递(为追求序列化效率,选用开源Hessian对对象进行序列化,java自身携带了序列化反序列化方法,此处选用自身提供的)

 

1.添加接口

package test01.producer;

public interface Pro01 {
    String produce(String proName);
}

2.添加实现类

package test01.producer;

public class Pro01Impl implements Pro01 {

    @Override
    public String produce(String proName) {
        System.out.println(proName);
        return "server say hi";
    }
    
}
3.添加调用时对象,包含要访问类类型、方法名以及方法中参数

package test01.common;

import java.io.Serializable;
import java.util.List;

public class RemoteObj implements Serializable {

    private static final long serialVersionUID = 5803202976390284233L;
    
    private String className;
    private String methodName;
    private List<ArgsObj> argsList;
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public List<ArgsObj> getArgsList() {
        return argsList;
    }
    public void setArgsList(List<ArgsObj> argsList) {
        this.argsList = argsList;
    }
    
    
}
4.添加参数对象,此处也可以不添加,根据内部通过反射获得类型

package test01.common;

import java.io.Serializable;

public class ArgsObj implements Serializable {
    
    private static final long serialVersionUID = 6879837066786687313L;
    
    private String argsType;
    private Object argsValue;
    public String getArgsType() {
        return argsType;
    }
    public void setArgsType(String argsType) {
        this.argsType = argsType;
    }
    public Object getArgsValue() {
        return argsValue;
    }
    public void setArgsValue(Object argsValue) {
        this.argsValue = argsValue;
    }
    
    
}

5.以TCP方式发布服务

package test01.producer;

import java.net.ServerSocket;
import java.net.Socket;
import test.thread.ServerRecive;

/**
 * 此示例只是简单实现,可将服务地址注册到zookeeper,访问时通过zookeeper获取服务地址
 * @author zsx
 *
 */
public class ProService {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(9999);
        
        while(true) {
            Socket socket = serverSocket.accept();
            new Thread(new ServerRecive(socket)).start();
        }
        
    }
}

 

package test.thread;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.List;

import test01.common.ArgsObj;
import test01.common.RemoteObj;
import test01.producer.Pro01;
import test01.producer.Pro01Impl;

public class ServerRecive implements Runnable {
    
    private Socket socket;
    
    public ServerRecive(Socket socket) {
        this.socket = socket;
    }
    
    
    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            
            //序列化对象
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            RemoteObj remoteObj = (RemoteObj)objectInputStream.readObject();
            //类-方法-参数
            String className = remoteObj.getClassName();
            String methodName = remoteObj.getMethodName();
            List<ArgsObj> argsList = remoteObj.getArgsList();
            
            //获取参数类型
            Class<?>[] clazzs = null;
            Object[] objs = null;
            if(argsList != null && argsList.size() > 0) {
                clazzs = new Class[argsList.size()];
                objs = new Object[argsList.size()];
                for(int i = 0; i < argsList.size(); i++) {
                    clazzs[i] = Class.forName(argsList.get(i).getArgsType());
                    objs[i] = argsList.get(i).getArgsValue();
                }
            }
            
            //此处如果实现IoC框架应该从IoC获取对象,暂不加入IoC框架
            if(className.equals(Pro01.class.getName())) {
                Pro01 pro01 = new Pro01Impl();
                Method method = pro01.getClass().getMethod(methodName, clazzs);
                
                //响应对象,包含类型,包含响应值
                Object obj = method.invoke(pro01, objs);
                    
                OutputStream outputStream = socket.getOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
                objectOutputStream.writeObject(obj);
            
            }
        } catch (Exception e) {
        }
    }
}
6.编写客户端测试访问

package test01.consumer;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import test01.common.ArgsObj;
import test01.common.RemoteObj;
import test01.producer.Pro01;

public class Con01 {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 9999);
        OutputStream outputStream = socket.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        RemoteObj remoteObj = new RemoteObj();
        remoteObj.setClassName(Pro01.class.getName());
        remoteObj.setMethodName("produce");
        List<ArgsObj> argsList = new ArrayList<>();
        ArgsObj argsObj = new ArgsObj();
        argsObj.setArgsType("java.lang.String");
        argsObj.setArgsValue("hello,Pro01");
        argsList.add(argsObj);
        remoteObj.setArgsList(argsList);
        objectOutputStream.writeObject(remoteObj);
        objectOutputStream.flush();
        
        InputStream inputStream = socket.getInputStream();
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        Object object = (Object)objectInputStream.readObject();
        if(object == null) {
        } else {
            System.out.println(object);
        }
        
        socket.close();
    }
}

 

注意:使用时需注意对象实现Serializable接口,接口间以流通信,需支持对象序列化和反序列化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值