项目描述
本项目主要是一个单线程的实现了redis一些命令的内存数据库。主要采用maven对项目实施代码管理,通过I/O流实现对命令的读取和输出。实现了对于redis的数据传输协议的解析以及对于lists、hashes中的命令进行了实现,如lpush、lpop、lrange、hset、hget等。
关键字
redis、协议解析、I/O、Socket、网络、TCP
源代码
Protocal.java
主要用于对redis数据传输协议的解析。
package com.niu;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
public class Protocol {
public static Object read(InputStream is) throws IOException {
return process(is);
}
//读命令
public static Command readCommand(InputStream is) throws Exception {
Object o = read(is);
// 作为 Server 来说,一定不会收到 "+OK\r\n"
if (!(o instanceof List)) {
throw new Exception("命令必须是 Array 类型");
}
//将读取到的命令保存在List中
List<Object> list = (List<Object>)o;
if (list.size() < 1) {
throw new Exception("命令元素个数必须大于 1");
}
//删除掉前面的命令单词
Object o2 = list.remove(0);
if (!(o2 instanceof byte[])) {
throw new Exception("错误的命令类型");
}
byte[] array = (byte[])o2;
String commandName = new String(array);
String className = String.format("com.niu.commands.%sCommand", commandName.toUpperCase());
Class<?> cls = Class.forName(className);
//
if (!Command.class.isAssignableFrom(cls)) {
throw new Exception("错误的命令");
}
Command command = (Command)cls.newInstance();
command.setArgs(list);
return command;
}
//读到的是Simple String类型的处理方式
private static String processSimpleString(InputStream is) throws IOException {
return readLine(is);
}
//解析error
private static String processError(InputStream is) throws IOException {
return readLine(is);
}
//读到的是integer类型的处理方式
private static long processInteger(InputStream is) throws IOException {
return readInteger(is);
}
//读到的是BulkString类型的处理方式
private static byte[] processBulkString(InputStream is) throws IOException {
int len = (int)readInteger(is);
if (len == -1) {
// "$-1\r\n" ==> null
return null;
}
byte[] r = new byte[len];
is.read(r, 0, len);
/*
for (int i = 0; i < len; i++) {
int b = is.read();
r[i] = (byte)b;
}
*/
// "$5\r\nhello\r\n";
is.read();
is.read();
return r;
}
private static List<Object> processArray(InputStream is) throws IOException {
int len = (int)readInteger(is);
if (len == -1) {
// "*-1\r\n" ==> null
return null;
}
List<Object> list = new ArrayList<>(len);
for (int i = 0; i < len; i++) {
try {
list.add(process(is));
} catch (RemoteException e) {
list.add(e);
}
}
return list;
}
//判断输入数据的类型
private static Object process(InputStream is) throws IOException {
int b = is.read();
if (b == -1) {
throw new RuntimeException("不应该读到结尾的");
}
switch (b) {
case '+':
return processSimpleString(is);
case '-':
throw new RemoteException(processError(is));
case ':':
return