新建三个model
服务提供方:rpc-consume
服务消费方:rpc-provide
提供远程调用:rpc-framework
服务提供方:rpc-consume代码
pom.xml:
<dependencies>
<dependency>
<groupId>demo</groupId>
<artifactId>framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
ProvideApplication类(用于暴露服务):
package com.provide.demo;
import com.framework.demo.RpcFramework;
import com.provide.demo.impl.UserServiceImpl;
public class ProvideApplication {
public static void main(String[] args) {
UserService userService = new UserServiceImpl() ;
//将服务暴露,供客户端消费
RpcFramework.export(userService, 8111);
}
}
UserService:
package com.provide.demo;
public interface UserService {
String sayHelloWordMethod(String parameter);
}
UserServiceImpl:
package com.provide.demo.impl;
import com.provide.demo.UserService;
public class UserServiceImpl implements UserService {
public String sayHelloWordMethod(String parameter) {
System.out.println(parameter);
return "hello 我是:Provide";
}
}
服务消费方:rpc-provide代码
pom.xml:
<dependencies>
<dependency>
<groupId>demo</groupId>
<artifactId>framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
ConsumerApplication类(用于获取代理对象,执行方法):
package com.provide.demo;
import com.framework.demo.RpcFramework;
public class ConsumerApplication {
public static void main(String[] args) {
UserService userService = RpcFramework.refer(UserService.class, "127.0.0.1", 8111);
String hello = userService.sayHelloWordMethod("hello 我是:Consumer");
System.out.println(hello);
}
}
UserService接口:
package com.provide.demo;
public interface UserService {
String sayHelloWordMethod(String parameter) ;
}
提供远程调用:rpc-framework代码
RpcFramework(核心类):
package com.framework.demo;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
public class RpcFramework {
//获取代理对象
public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) {
/**
* JDK提供的动态代理,要求被代理的类必须实现一个接口
*
*/
//返回代理对象
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//创建Socket客户端对象,绑定服务端的ip和端口
Socket socket = new Socket(host, port);
//构造序列化流,用于向服务端写入
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//方法名
//writeUTF(String str):写出一个UTF-8编码的字符串
oos.writeUTF(method.getName());
//方法形参类型
//writeObject(Object obj)写入一个对象
oos.writeObject(method.getParameterTypes());
//方法参数
oos.writeObject(args);
//反序列化流,用于接收服务端的返回值
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//读取
Object obj = ois.readObject();
return obj;
}
});
}
/**
* 将服务暴露,供消费放方调用
*
* @param obj
* @param port
*/
public static void export(final Object obj, final int port) {
try {
//创建ServerSocket服务端对象,向系统指定端口
ServerSocket serverSocket = new ServerSocket(port);
//轮询
while (true) {
final Socket accept = serverSocket.accept();
//开启多线程,处理消息,返回结果
new Thread(() -> {
try {
/**
* 注意:
* 使用序列化对象时的顺序
* 服务端先建立ObjectInputStream后建立ObjectOutputStream
* 则对应地客户端要先建立ObjectOutputStream后建立ObjectInputStream
* 否则会造成两方互相等待数据而导致死锁。
*
* 原因是建立ObjectInputStream对象是需要先接收一定的header数据
* 接收到这些数据之前会处于阻塞状态。
*/
//反序列化对象
ObjectInputStream ois = new ObjectInputStream(accept.getInputStream());
//方法名
String methodName = ois.readUTF();
//形参类型
Class<?>[] paramsTypes = (Class<?>[]) ois.readObject();
//方法参数
Object[] args = (Object[]) ois.readObject();
//使用反射,获得方法对象
Method method = obj.getClass().getMethod(methodName, paramsTypes);
Object invoke = method.invoke(obj, args);
//将方法的返回值写会客户端
ObjectOutputStream oos = new ObjectOutputStream(accept.getOutputStream());
oos.writeObject(invoke);
} catch (Exception e) {
e.printStackTrace();
}
}
).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试,先启动提供方,再启动消费方
提供方打印结果:
消费方打印结果:
ok,以上。