JAVA手写实现简单版Jedis客户端----超详细

JAVA手写实现简单版Jedis客户端----超详细

已更新将手写的Jedis加入到springboot的自动配置,并可实现yml中修改配置

传送门:(将手写Jedis集成到springboot自动配置)

首先写之前,咱们聊聊手写的思路,聊到redis,咱们都知道是一款NOSQL的缓存数据库,可以用来验证登陆,可以存放热点数据,可以用来做秒杀,用来流量销峰。那么redis到底是怎么通信的呢?JAVA又是如何与redis建立连接的呢?
看下图:
在这里插入图片描述
搞通了流程图之后,那么有一个问题,网络通信用的是什么协议来进行传输呢?答案是:RESP协议来通信。
那么RESP协议长啥样呢?
例:

  *3    数组3
 
  $3	字符3
  SET
  
  $6	字符串6
  xiangan
  		字符串4
  $4
  2020

    //"+OK\r\n" 每一个结尾都需要一个换行
    //For Simple Strings the first byte of the reply is "+"
	//For Errors the first byte of the reply is "-"
	//For Integers the first byte of the reply is ":"
	//For Bulk Strings the first byte of the reply is "$"
	//For Arrays the first byte of the reply is "*"

好了,协议搞明白了,那么我们直接用代码来简单实现一个Jedis客户端吧

需要用到的有3个类,分别解释一下:
TestJedis:API层
TestProtocol:协议格式处理
Connection:连接,发送数据层。
Test测试类:

TestJedis jedis = new TestJedis("*.*.*.*", 6379);
		System.out.println(jedis.set("haha", "haha"));
		System.out.println(jedis.get("haha"));

TestJedis类:

/**
 * 
 * @author An
 * JedisClient API操作层
 *
 */
public class TestJedis {
	Connection connection; //连接层
	
	public TestJedis(String host,int port) {
	//构造方法传入:ip地址和端口号
		this.connection = new Connection(host, port);
	}
	
	//APIset方法
	public String set(String key,String value) {
		connection.sendcommit(Command.SET,key.getBytes(),value.getBytes());
		return connection.getStatusCodereply();
	}
	//API  get方法
	public String get(String key) {
	connection.sendcommit(Command.GET,key.getBytes());
		return connection.getStatusCodereply();
	}
}

Connection类:

/**
 * 
 * @author An
 *
 */
public class Connection {
	
	private Socket socket;//socket连接
	private String host;//主机ip地址
	private int port;//端口号
	private OutputStream outputStream;//输出流
	private InputStream inputStream;//输入流
	
	public Connection(String host,int port) {
		this.host = host;
		this.port = port;
	}
	
	public Connection connection() {
		try {
			//建立socket连接
			socket = new Socket(host, port);
			//获取输入输出流
			inputStream = socket.getInputStream();
			outputStream = socket.getOutputStream();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return this;
	}
	/**
	 * 发送数据和命令
	 * @return
	 */
	public Connection sendcommit(Command command,byte[]...bs) {
		connection();
		TestProtocol.sendCommand(outputStream, command, bs);
		return this;
	}
	/**
	*	接收服务端返回的数据
	*/
	public String getStatusCodereply() {
		byte[] bytes = new byte[1024];
		
		try {
			inputStream.read(bytes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return new String(bytes);
	}
	
}

TestProtocol类:

/**
 * 
 * @author An
 * 
 * 协议数据格式处理
 *
 */
public class TestProtocol {
	public static final String DOLLAR_BYTE="$";//字符串
	public static final String ASTERISK_BYTE="*";//数组
	public static final String BLANK_STRING="\r\n";//换行
	
	
	
	//封装redis需要的数据
	public static void sendCommand(OutputStream os,Command command,byte[]...bs ) {
		StringBuffer sb = new StringBuffer();
		sb.append(ASTERISK_BYTE).append(bs.length+1).append(BLANK_STRING);
		sb.append(DOLLAR_BYTE).append(command.name().length()).append(BLANK_STRING);
		sb.append(command.name()).append(BLANK_STRING);
		System.out.println(command.name());
		for (byte[] bs2 : bs) {
			sb.append(DOLLAR_BYTE).append(bs2.length).append(BLANK_STRING);
			sb.append(new String(bs2)).append(BLANK_STRING);
			
		}
		try {
			//发送
			os.write(sb.toString().getBytes());
		} catch (IOException e) {			
			e.printStackTrace();
		}
	}
	
	
	//定义枚举
	public static enum Command{
		GET,SET,KEYS
	}
}

测试一下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

好了,大功告成!!!码字不易,觉得有帮助的,不妨点个赞再走~~~
您的点赞将是作者持续更新的动力!!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值