java基础巩固-宇宙第一AiYWM:为了维持生计,手写RPC~Version02(封装一个Stub代理(约定俗成的名字)出来,客户端只需看懂或调用这个Stub代理中方法即可实现远程调用)整起

Version02:
Version01中,所有的代码细节都暴露出来,但是这不一定是好事。转动咱们聪慧的大脑就可以想到Java里面的三大特性~封装、继承和多态。那先用封装试试水喽:
在这里插入图片描述

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package entity;

import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 客户端敏小言与服务端小胡都已知的实体,客户端需要得到这个pojo对象数据,服务端需要操作这个对象,咱们这种情境下就是服务器需要去按照客户端提供的信息查询一下这个对象,再把查找到对象返还给客户端
 * 
 * 比如,本机上另外一个类想拿到我这个Pilliow对象去使用,拿到给他这不就是本地通信或者传输嘛 ,但是,如果另外一台机器上的一个东西想拿到我这个Pilliow对象去使用,拿给他这不就是远程通信嘛
 * @author HuHongBo
 * @version 2022年5月5日
 */
//@Builder
//@Data
//@NoArgsConstructor
//@AllArgsConstructor
public class Pilliow implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String clothesColor;

	public Pilliow(Integer id, String clothesColor) {
		super();
		this.id = id;
		this.clothesColor = clothesColor;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getClothesColor() {
		return clothesColor;
	}

	public void setClothesColor(String clothesColor) {
		this.clothesColor = clothesColor;
	}

	@Override
	public String toString() {
		return "Pilliow [id=" + id + ", clothesColor=" + clothesColor + "]";
	}

}

然后,小胡把id给敏小言发过去时,自己就开始阻塞等待:
什么时候把Pillow发送来呢?
什么时候把Pillow发送来呢?什么时候把Pillow发送来呢?
什么时候把Pillow发送来呢?什么时候把Pillow发送来呢?什么时候把Pillow发送来呢?

然后敏小言那边作为服务端,调用服务(方法)用id查找到那个Pillow后,就开始把这个Pillow给小胡发过去。
然后小胡收到了Pillow后,就去把Pillow塞到柜子里等顾客去取就行了。
其中有些偷懒细节,看注释:
在这里插入图片描述

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package client;

import entity.Pilliow;
import server.Stub;

/**
 * 客户端是需要把id=221这个id值写给服务器端,这样服务器端才能帮咱们按照这个id去找到这个Pillow呀
 * 	由于网络上只能传输二进制,所以咱们得把这个id值,也就是221转换成为二进制
 * 	Java中可以用这三句代码,就会自动帮咱们把id这个221值转为221对应的二进制
 * 		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		dataOutputStream.writeInt(221);
 * 
 * @author HuHongBo
 * @version 2022年5月12日
 */
public class Client {
	public static void main(String[] args) throws Exception {
		Stub stub = new Stub();
		System.out.println(stub.getPilliowByPilliowId(221));
		
	}
}

在这里插入图片描述

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package server;

import entity.Pilliow;

/**
 * 定义客户端需要调用,服务端需要提供的服务接口
 * getUserByUserId()这个方法或者说这个方法所在的类,就是咱们的一个服务呀,供别人调用的
		 * 
		 * 那我调用服务的思路就是:我想查id为221的那个人,我客户端是不是得先把id=221这个id写给服务端
		 * 然后服务端查到这个人后,转成二进制给我客户端再返回回来(写回来)
		 * 我这边收到之后再进行解析
 * @author HuHongBo
 * @version 2022年5月5日
 */
public interface PilliowService {
	/**
	 * 客户端通过这个接口调用服务端的实现类
	 * @param id
	 * @return
	 * @author HuHongBo
	 */
    Pilliow getPilliowByPilliowId(Integer id);
}

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package server;
import entity.Pilliow;

/**
 * getPilliowByPilliowId()这个方法或者说这个方法所在的类,就是咱们的一个服务呀,供别人调用的
		 * 
		 * 那我调用服务的思路就是:我想查id为221的那个人,我客户端是不是得先把id=221这个id写给服务端
		 * 然后服务端查到这个人后,转成二进制给我客户端再返回回来(写回来)
		 * 我这边收到之后再进行解析
 * @author HuHongBo
 * @version 2022年5月5日
 */
public class PilliowServiceImpl implements PilliowService{

	@Override
	public Pilliow getPilliowByPilliowId(Integer id) {
		/**
		 * 当然,实体类中的这些成员变量的值一般实际中都是从数据库中或者说缓存中查出来的
		 */
		return new Pilliow(id, "black 卫衣");
	}

}

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import entity.Pilliow;


/**
 * 
 * getPilliowByPilliowId()这个方法或者说这个方法所在的类,就是咱们的一个服务呀,供别人调用的
* 
* 那我调用服务的思路就是:我想查id为221的那个人,我客户端是不是得先把id=221这个id写给服务端
* 然后服务端查到这个人后,转成二进制给我客户端再返回回来(写回来)
* 我这边收到之后再进行解析
 * 
 * @author HuHongBo
 * @version 2022年5月12日
 */
public class Server {
	private static boolean flag = true;
	
	public static void main(String[] args) throws Exception{
		/**
		 * 别人可以通过这个端口来远程连接我这个Server,也就是服务
		 */
		ServerSocket serverSocket = new ServerSocket(2221);
		while(flag){
			/**
			 * 通过accept接收一个客户端连接
			 */
			Socket socket = serverSocket.accept();
			/**
			 * 对客户端的连接进行处理
			 */
			process(socket);
			socket.close();
		}
	}

	/**
	 * 
	 * @param socket
	 * @throws Exception
	 * @author HuHongBo
	 */
	private static void process(Socket socket) throws Exception {
		/**
		 * 拿到输入流
		 */
		InputStream inputStream = socket.getInputStream();
		OutputStream outputStream = socket.getOutputStream();
		DataInputStream dataInputStream = new DataInputStream(inputStream);
		DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
		
		/**
		 * 从输入流中解析出,谁把这个id传给我的,我把这个id读出来
		 * 	刚刚咱们在客户端不是发过来一个id为221的整数对应的二进制,然后还把这个二进制转为字节数组了嘛
		 * 下来咱们通过readInt()把代表221的字节数组都进来,转换成为一个int类型的id
		 */
		int id = dataInputStream.readInt();
		PilliowServiceImpl serviceImpl = new PilliowServiceImpl();
		/**
		 * getPilliowByUPilliowId()这个方法或者说这个方法所在的类,就是咱们的一个服务呀,供别人调用的
		 * 
		 * 那我调用服务的思路就是:我想查id为221的那个人,我客户端是不是得先把id=221这个id写给服务端
		 * 然后服务端查到这个人后,转成二进制给我客户端再返回回来(写回来)
		 * 我这边收到之后再进行解析,我服务器端,拿到了这个id值然后就能找到一个对应的Pilliow嘛
		 */
		Pilliow pilliow = serviceImpl.getPilliowByPilliowId(id);
		/**
		 * 把得到的pilliow写出去
		 * 	其实这里我偷了个懒,因为我知道你Pilliow就俩属性id和clothesColor这俩属性,我把这俩属性写给你也就相当于把这个Pilliow对象写给你了嘛
		 */
		dataOutputStream.writeInt(pilliow.getId());
		dataOutputStream.writeUTF(pilliow.getClothesColor());
		dataOutputStream.flush();
		
	}
}

/**
 * Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
 */
package server;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import entity.Pilliow;

/**
 * 封装一个代理出来,别人只需看懂或者说调用这个getPilliowByPilliowId方法即可。我其实很想把名字起为Proxy而不是Stub,但是人家约定俗成代理中介叫stub,就按照人家的来吧
 * @author HuHongBo
 * @version 2022年5月12日
 */
public class Stub {
	/**
	 * 客户端通过这个接口调用服务端的实现类
	 * @param id
	 * @return
	 * @author HuHongBo
	 */
    public Pilliow getPilliowByPilliowId(Integer id) throws Exception{
    	/**
    	 * 连网络,把id这个221值写出去到服务器端,让他帮忙按id找Pillow
    	 */
    	Socket socket = new Socket("127.0.0.1", 2221);
    	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    	DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
    	dataOutputStream.writeInt(221);
    	
    	/**
    	 * 把表示221这个id值的二进制转为真正的int字节数组,再通过.write方法把这个字节数组给写出去,然后这个字节数组,也就是id=221才能到服务器端
    	 */
    	socket.getOutputStream().write(byteArrayOutputStream.toByteArray());
    	socket.getOutputStream().flush();
    	
    	/**
    	 * 他服务器那边偷了个懒嘛,虽然说后面有更高级的方式可以把Pillow些过来给我,但是现在他就是在偷懒,只把Pillow的俩属性写过来了
    	 * 那我客户端DataInputStream就在这里阻塞着,等着读,服务器端发来的Pillow对象
    	 */
    	DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
    	/**
    	 * 废话,既然你是偷懒,传俩属性过来,我这边也是把id和clothesColor分别读进来就行
    	 */
    	int receivedId = dataInputStream.readInt();
    	String clothesColor = dataInputStream.readUTF();
    	Pilliow pillow = new Pilliow(receivedId, clothesColor);
    	
    	dataOutputStream.close();
    	socket.close();
    	return pillow;
    }
}

但是此时缺陷依旧:
我要有其他方法,或者说我想通过id找其他东西,或者说通过除id之外的参数找其他东西怎么办,我也不想自己手动写每个类的代理类,怎么办?

所以Version03应运而生
…未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值