- 编写公共项目—自定义fastjson序列化协议,存放接口
public class JSONSerializer implements Serializer {
@Override
public byte[] serialize(Object object) {
return JSON.toJSONBytes(object);
}
@Override
public <T> T deserialize(Class<T> clazz, byte[] bytes) {
return JSON.parseObject(bytes, clazz);
}
}
public class RpcDecoder extends ByteToMessageDecoder {
private Class<?> clazz;
private Serializer serializer;
public RpcDecoder(Class<?> clazz, Serializer serializer) {
this.clazz = clazz;
this.serializer = serializer;
}
@Override
protected void decode(ChannelHandlerContext channelHandlerContext,
ByteBuf byteBuf, List<Object> list) throws Exception {
//因为之前编码的时候写入一个Int型,4个字节来表示长度
if (byteBuf.readableBytes() < 4) {
return;
}
//标记当前读的位置
byteBuf.markReaderIndex();
int dataLength = byteBuf.readInt();
if (byteBuf.readableBytes() < dataLength) {
byteBuf.resetReaderIndex();
return;
}
byte[] data = new byte[dataLength];
//将byteBuf中的数据读入data字节数组
byteBuf.readBytes(data);
Object obj = serializer.deserialize(clazz, data);
list.add(obj);
}
}
public class RpcRequest {
private String requestId;
/** 类名 */
private String className;
/** 方法名 */
private String methodName;
/** 参数类型 */
private Class<?>[] parameterTypes;
/** 入参 */
private Object[] parameters;
getter setter....
}
public interface Serializer {
/**
* java对象转换为二进制
*
* @param object
* @return
*/
byte[] serialize(Object object) throws IOException;
/**
* 二进制转换成java对象
*
* @param clazz
* @param bytes
* @param <T>
* @return
*/
<T> T deserialize(Class<T> clazz, byte[] bytes) throws IOException;
}
public class RpcEncoder extends MessageToByteEncoder {
private Class<?> clazz;
private Serializer serializer;
public RpcEncoder(Class<?> clazz, Serializer serializer) {
this.clazz = clazz;
this.serializer = serializer;
}
@Override
protected void encode(ChannelHandlerContext channelHandlerContext,
Object msg, ByteBuf byteBuf) throws Exception {
if (clazz != null && clazz.isInstance(msg)) {
byte[] bytes = serializer.serialize(msg);
byteBuf.writeInt(bytes.length);
byteBuf.writeBytes(bytes);
}
}
}
- 编写客户端
1)启动类—调用方法,打印结果
public class ConsumerBoot {
public static void main(String[] args) throws InterruptedException {
//1-获取代理对象
IUserService userService = (IUserService) RPCConsumer.createProxy(IUserService.class);
int i = 0;
try {
while(true){
String name = "ok :" + i++;
System.out.println("发起调用,入参====>>> "+name);
String result = userService.sayHello(name);
System.out.println("返回结果,出参====>>> "+result);
Thread.sleep(2000);
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)消费者—初始化客户端,实现动态代理方法
public class RPCConsumer {
//1.创建一个线程池对象 处理自定义事件
private static ExecutorService executorService =
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//2.生命一个自定义事件处理器 UserClientHandler
private static UserClientHandler userClientHandler;
//3.编写方法初始化客户端 (创建连接池 bootStrap 设置 bootstrap 连接服务器)
public static void initClient() throws InterruptedException {
//初始化UserClientHandler
userClientHandler = new UserClientHandler();
EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(nioEventLoopGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new RpcEncoder(RpcRequest.class,new JSONSerializer()));
pipeline.addLast(new RpcDecoder(Object.class,new JSONSerializer()));
pipeline.addLast(userClientHandler);
}
});
bootstrap.connect("127.0.0.1",8999).sync();
}
//4.编写一个方法,使用JDK动态代理创建对象
public static Object createProxy(Class<?> serviceClass){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{serviceClass}, (proxy, method, args) -> {
if (method.getDeclaringClass() == Object.class){
return method.invoke(args);
}
//1.初始化客户端client
if (userClientHandler == null){
initClient();
}
//2.给UserClientHandler设置param参数
RpcRequest rpcRequest = new RpcRequest();
rpcRequest.setClassName(method.getDeclaringClass().getName());
rpcRequest.setMethodName(method.getName());
rpcRequest.setParameterTypes(method.getParameterTypes());
rpcRequest.setParameters(args);
userClientHandler.setParam(rpcRequest);
//3.使用线程池开启线程处理call,并返回结果
Object result = executorService.submit(userClientHandler).get();
//4.return 结果
return result;
});
}
}
3)消费者Handler—处理服务端返回的结果
public class UserClientHandler extends ChannelInboundHandlerAdapter implements Callable {
//1.定义成员变量
private ChannelHandlerContext context;//事件处理器上下文对象,可以存储handler信息,写操作
private String result;//记录服务器返回的数据
private RpcRequest param;//记录将要反送给服务器的数据
//2.实现channelActive 客户端和服务器连接时,该刚发自动执行
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//初始化ChannelHandlerContext;
this.context = ctx;
}
//3.实现channelRead 当我们读到服务器数据,该方法自动执行
@Override
public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将读到的服务器数据msg,设置为成员变量的值
result = msg.toString();
notify();
}
//4.将客户端的数据写到服务器
public synchronized Object call() throws Exception {
//context给服务器写数据
context.writeAndFlush(param);
wait();
return result;
}
//5.设置参数的方法
public void setParam(RpcRequest param){
this.param = param;
}
}
3.编写服务端
1)启动类—启动服务
@SpringBootApplication
public class ServerBoot {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ServerBoot.class,args);
ProviderServer providerServer = applicationContext.getBean(ProviderServer.class);
providerServer.startServer(8999);
}
}
2)接口的实现方法
@Service
public class UserServiceImpl implements IUserService {
public String sayHello(String msg) {
System.out.println("are you ok ?"+msg);
return "success";
}
}
3)服务端
@Component
public class ProviderServer {
@Autowired
private UserServiceHandler serverHandler;
public void startServer(int port) throws InterruptedException {
//1.创建两个线程池对象
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
//2.创建服务端的启动引导对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//3.配置启动引导对象
serverBootstrap.group(bossGroup,workGroup)
//设置通道为NIO
.channel(NioServerSocketChannel.class)
//创建监听channel
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
//获取管道对象
ChannelPipeline pipeline = nioSocketChannel.pipeline();
//给管道对象pipeLine 加解码(服务器端 解码用RpcRequest,加码用Object)
pipeline.addLast(new RpcEncoder(Object.class,new JSONSerializer()));
pipeline.addLast(new RpcDecoder(RpcRequest.class,new JSONSerializer()));
pipeline.addLast(serverHandler);
}
});
//4.绑定端口
serverBootstrap.bind(port).sync();
}
}
4)服务端Handler—监听处理传入的RpcRequest
@Component
public class UserServiceHandler extends ChannelInboundHandlerAdapter implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//msg: UserService#sayHello#are you ok
RpcRequest rpcRequest = (RpcRequest) msg;
System.out.println("rpcRequest====>>>> "+rpcRequest);
//拿到spring管理的对象
Class<?> targetClass = Class.forName(rpcRequest.getClassName());
Object bean = applicationContext.getBean(targetClass);
//拿到要调用的方法
Method method = targetClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
//拿到结果
Object result = method.invoke(bean, rpcRequest.getParameters());
//将出参写入通道,并推送给客户端
ctx.writeAndFlush(result);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}