先来看看场景
现在有商品服务和订单服务两个应用程序,订单服务需要去调用商品服务的queryById接口获取商品数据。
服务端代码
- 简单商品实体
package cn.cuit.rpc.api;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
// 这里使用lombok工具可以通过注解帮我们实现Getter和Setter,ToString等方法
@Getter
@Setter
@ToString
public class ProductInfo implements Serializable { // 注意:这里必须实现序列化接口,因为对象需要在网络中传输
private static final long serialVersionUID = -4399775992014494802L;
private Long id;
private String productName;
private BigDecimal price;
// public final Long getId() {
// return id;
// }
// public final void setId(Long id) {
// this.id = id;
// }
// public final String getProductName() {
// return productName;
// }
// public final void setProductName(String productName) {
// this.productName = productName;
// }
// public final BigDecimal getPrice() {
// return price;
// }
// public final void setPrice(BigDecimal price) {
// this.price = price;
// }
// @Override
// public String toString() {
// return "ProductInfo [id=" + id + ", productName=" + productName + ", price=" + price + "]";
// }
}
- 服务端接口
package cn.cuit.rpc.api;
public interface ProductInfoService {
ProductInfo queryById(Long id);
}
- 服务端接口实现
package cn.cuit.rpc.api;
import java.math.BigDecimal;
public class ProductInfoServiceImpl implements ProductInfoService {
public ProductInfo queryById(Long id) {
ProductInfo productInfo = new ProductInfo();
productInfo.setId(id);
productInfo.setProductName("CUIT");
productInfo.setPrice(new BigDecimal("25.8"));
return productInfo;
}
}
- 服务端提供者
package cn.cuit.rpc.api;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端[注意点:客户端与服务端两边的接口的包名要一致,因为动态代理的时候基于接口,接口的类全路径名称需要一致]
*
*/
public class ServiceProviderMain {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println(">>>>>>>>>>>>>服务端已经启动,端口号是8888<<<<<<<<<<<<<<" + ProductInfoService.class.getName());
while (true) {
// 获取服务端接受到的客户端Socket
Socket socket = serverSocket.accept();
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
// 读取客户端发过来的内容
String apiServiceClassName = inputStream.readUTF();
String methodName = inputStream.readUTF();
Class<?>[] paramsType = (Class<?>[]) inputStream.readObject();
Object[] args4Method = (Object[]) inputStream.readObject();
Class<?> clazz = null;
if (ProductInfoService.class.getName().equals(apiServiceClassName)) {
clazz = ProductInfoServiceImpl.class; // 这里是实现类
}
// 开始反射调用服务方法
Method targetMethod = clazz.getMethod(methodName, paramsType);
Object invokeResult = targetMethod.invoke(clazz.newInstance(), args4Method);
// 把调用结果写回客户端
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(invokeResult);
outputStream.flush();
inputStream.close();
outputStream.close();
socket.close();
Thread.sleep(Integer.MAX_VALUE);
serverSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端代码
- 商品实体
package cn.cuit.rpc.api;
import java.io.Serializable;
import java.math.BigDecimal;
public class ProductInfo implements Serializable {
private static final long serialVersionUID = -4399775992014494802L;
private Long id;
private String productName;
private BigDecimal price;
public final Long getId() {
return id;
}
public final void setId(Long id) {
this.id = id;
}
public final String getProductName() {
return productName;
}
public final void setProductName(String productName) {
this.productName = productName;
}
public final BigDecimal getPrice() {
return price;
}
public final void setPrice(BigDecimal price) {
this.price = price;
}
@Override
public String toString() {
return "ProductInfo [id=" + id + ", productName=" + productName + ", price=" + price + "]";
}
}
- 与服务端相同的接口【基于Java的动态代理实现,所以要基于接口】
package cn.cuit.rpc.api;
public interface ProductInfoService {
ProductInfo queryById(Long id);
}
- 客户端调用服务端
package cn.cuit.rpc.api;
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.Socket;
/**
* 客户端[注意点:两边的接口的包名要一致]
*/
public class ServiceCustomerMain {
public static void main(String[] args) {
ProductInfoService productInfoService = (ProductInfoService) rpc(ProductInfoService.class);
ProductInfo productInfo = productInfoService.queryById(100L);
System.out.println("服务端返回数据:" + productInfo);
}
public static Object rpc(final Class<?> clazz) {
return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 指定要连接的服务端的IP和端口
Socket socket = new Socket("127.0.0.1", 8888);
String apiServiceClassName = clazz.getName();
System.out.println(apiServiceClassName);
String methodName = method.getName();
Class<?>[] paramsType = method.getParameterTypes();
// 这里的写是写给自己连接的服务端的内容
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeUTF(apiServiceClassName);
outputStream.writeUTF(methodName);
outputStream.writeObject(paramsType);
outputStream.writeObject(args);
outputStream.flush();
// 读取从服务端返回的内容
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
Object readObject = inputStream.readObject();
outputStream.close();
inputStream.close();
socket.close();
return readObject;
}
});
}
}
- 开始测试:
首先启动服务端:
启动客户端:
LZ第一次写博客,以后请各路大神多多指教