【ITer自我修养之成长日记】Redis的java API操作

一、导入依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

二、redis架构示意图

在这里插入图片描述

三、徒手解剖redis

1.Test

1.1 运行redis-server和redis-cli
1.2 编码
package cn.redis;

import redis.clients.jedis.Jedis;

public class Test {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        jedis.set("myname", "LQ");
        System.out.println(jedis.get("myname"));
    }
}
1.3 redis-cli端查看

在这里插入图片描述

2. 模拟redis服务端 – HackSockerServer

2.1 编码
package cn.redis.hack;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 伪装 redis 的服务端
 *
 * */
public class HackSockerServer {
    public static void main(String[] args) throws IOException {
        System.out.println("HackSockerServer已启动.....");
        ServerSocket serverSocket = new ServerSocket(6379);
        //接收数据
        Socket accept = serverSocket.accept();
        byte[] buffer = new byte[1024];
        accept.getInputStream().read(buffer);
        System.out.println(new String(buffer));
    }
}
2.2 Test 测试类
package cn.redis;

import redis.clients.jedis.Jedis;

public class Test {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        jedis.set("myname", "LQ");
        System.out.println(jedis.get("myname"));
    }
}
分别运行HackSockerServer和Test
结果
HackSockerServer已启动.....
*3
$3
SET
$6
myname
$2
LQ
官网说明 https://redis.io/topics/protocol
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 "*" -->数组
Simple Strings are encoded in the following way: a plus character, followed by a string that cannot contain a CR or LF character (no newlines are allowed), terminated by CRLF (that is "\r\n").
那么以上结果可以理解为:
*3  3个数组
=====
$3	3个字符串
SET	
===========
$6 6个字符串
myname
===========
$2 2个字符串
LQ
===========

3.transfer层原理+编码

3.1 编码
package cn.redis.transfer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Conncetion {
    private Socket socket;
    private String host;
    private int port;
    private OutputStream outputStream;
    private InputStream inputStream;

    public Conncetion(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void connect() throws IOException {
        try {
            socket = new Socket(host, port);
            inputStream = socket.getInputStream();
            outputStream=socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4.根据以上理解模拟protocol层(协议层)

4.1 编码
package cn.redis.protocol;

/*
*  模拟协议层工作原理:加入命令格式如下
    *3
    $3
    SET
    $6
    myname
    $2
    LQ
* */

import java.io.IOException;
import java.io.OutputStream;

public class Protocol {

    public static final String ASTERISK_STRING = "*"; //asterisk --> 星号
    public static final String DOLLAR_STRING = "$";
    public static final String BLANK_STRING = "\r\n";

    public static enum Command{
        GET,SET
    }

    public static void protocolAnalysis(OutputStream os, Protocol.Command command, byte[]...args) {
        StringBuilder sb = new StringBuilder();
        sb.append(ASTERISK_STRING).append(args.length + 1).append(BLANK_STRING); //相当于  *3
        sb.append(DOLLAR_STRING).append(command.name().length()).append(BLANK_STRING); //相当于  $3
        sb.append(command.name()).append(BLANK_STRING);  //相当于 SET
        for (byte[] arg : args) {
            sb.append(DOLLAR_STRING).append(arg.length).append(BLANK_STRING);
            sb.append(new String(arg)).append(BLANK_STRING);
        }

        System.out.println(sb.toString());

        try {
            os.write(sb.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5.根据以上理解模拟client层(API层)

5.1 编码
package cn.redis.client;

import cn.redis.protocol.Protocol;
import cn.redis.safe.SafeEncode;
import cn.redis.transfer.Transfer;
import redis.clients.util.SafeEncoder;

import java.io.IOException;

/**
 * 暴露给其他人进行调用的
 * */
public class ClinetOp {

    private Transfer conncetion;

    //连接
    public ClinetOp(String host, int port) {
        conncetion = new Transfer(host, port);
    }

    //暴露此调用接口,此调用接口的底层 还是要去操作 redis, 所以构造方法如上
      //在写 GET 方法时,想到返回信息,所以 另写了getStatusReply()
    public String set(String key, String value) throws IOException {
        conncetion.sendCommand(Protocol.Command.SET, SafeEncoder.encode(key), SafeEncoder.encode(value));
        return conncetion.getStatusReply();
    }

    //在理解 SET 方法的基础上,写GET方法,向 架构师 方向更进一步
    public String get(String key) throws IOException {
        conncetion.sendCommand(Protocol.Command.GET, SafeEncoder.encode(key));
        return conncetion.getStatusReply();
    }
}

6.结果验证

6.2 SET 的Test 测试类
package cn.redis;

import cn.redis.client.ClinetOp;
import redis.clients.jedis.Jedis;

import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
	  /**
	   * 自己实现 redis 的架构  由上到下
	   * 1.API层 client
	   * 2.协议层 protocol
	   * 3.传输层 transfer
	   * */
        ClinetOp clinetOp = new ClinetOp("192.168.1.100",6379);
        clinetOp.set("mytest", "success");
        //System.out.println(clinetOp.get("mytest"));
    }
}
6.2 SET 的结果
*3
$3
SET
$6
mytest
$7
success
6.3 GET 的Test 测试类
package cn.redis;

import cn.redis.client.ClinetOp;
import redis.clients.jedis.Jedis;

import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
	  /**
	   * 自己实现 redis 的架构  由上到下
	   * 1.API层 client
	   * 2.协议层 protocol
	   * 3.传输层 transfer
	   * */
        ClinetOp clinetOp = new ClinetOp("192.168.1.100",6379);
        clinetOp.set("mytest", "success");
        System.out.println(clinetOp.get("mytest"));
    }
}
6.4 redis-cli 验证

在这里插入图片描述

6.5 GET 的结果
*3
$3
SET
$6
mytest
$7
success
====  以上是 SET 的结果  =====	
*2
$3
GET
$6
mytest

$7
success
====  以上是 GET 的结果
6.6 redis-cli 验证

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值