Redis通过RESP协议进行客户端与服务端的通信,不了解的可以参考我的上篇博客–RESP协议,根据RESP协议,我们可以实现简易的redisClient,下面为我实现的一个简易客户端,包括连接redis,密码验证、get、set这几个功能。实现如下:
public class MyRedisClient {
private int port;
private String host;
private String password;
private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
private final static String END_SIGN = "\r\n";
public MyRedisClient(String host) {
this(6379, host);
}
public MyRedisClient(int port, String host) {
this(port, host, null);
}
public MyRedisClient(int port, String host, String password) {
this.port = port;
this.host = host;
this.password = password;
connect();
verifyPassword();
}
private void connect(){
try {
socket = new Socket(host, port);
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
} catch (IOException e) {
System.err.println("连接失败......");
e.printStackTrace();
}
}
private String executeCmd(String... params){
StringBuilder clientMsg = new StringBuilder();
clientMsg.append("*").append(params.length).append(END_SIGN);
for (String param : params){
clientMsg.append("$").append(param.getBytes().length).append(END_SIGN)
.append(param).append(END_SIGN);
}
String serverMsg = "";
try {
outputStream.write(clientMsg.toString().getBytes());
byte[] bytes = new byte[1024];
inputStream.read(bytes);
serverMsg = new String(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return serverMsg;
}
private void verifyPassword(){
if (password == null){
return;
}
System.out.println(executeCmd("AUTH", password));
}
public String get(String key){
return executeCmd("GET", key);
}
public String set(String key, String value){
return executeCmd("SET", key, value);
}
}
首先是创建连接,包括ip、port、password这个几个参数,可部分缺省,通过构造方法来完成连接的创建,创建过程主要为两步,分别是连接socket和验证密码。
连接socket和创建普通的TCp连接没有区别,验证密码实际上就是根据RESP协议组装信息,然后通过socket进行数据交互来完成的。
对于这里的信息组装方法我是通过不定参数列表来实现的,这样实际上不仅支持我上面写的几个命令,对于大多数命令同样也是支持的。
private String executeCmd(String... params) {
StringBuilder clientMsg = new StringBuilder();
clientMsg.append("*").append(params.length).append(END_SIGN);
for (String param : params) {
clientMsg.append("$").append(param.getBytes().length).append(END_SIGN)
.append(param).append(END_SIGN);
}
String serverMsg = "";
try {
outputStream.write(clientMsg.toString().getBytes());
byte[] bytes = new byte[1024];
inputStream.read(bytes);
serverMsg = new String(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return serverMsg;
}
首先根据不定参数列表的长度确定RESP协议中数组的长度,然后再根据后续的参数继续填充后续信息,完成信息的组装,接着讲信息发送给服务端,再接收服务端反馈的信息,命令执行到此就完成了,这种使用不定参数列表的命令组装方式可以执行绝大部分常用命令请求,这里这封装了密码验证、get、set这三个命令。
测试代码如下:
public class MyRedisClientTest {
public static void main(String[] args) {
MyRedisClient myRedisClient = new MyRedisClient(6379, "www.wkcaeser.com", "WKgui000!");
System.out.println(myRedisClient.get("name"));
System.out.println(myRedisClient.set("testMyClient", "true"));
}
}