zl程序教程

您现在的位置是:首页 >  .Net

当前栏目

使用了不到200行的核心代码就实现了一个美轮美奂的Redis客户端

2023-02-18 16:28:48 时间

背景

工作长达10多年来,也许是Redis命令敲多了,突然有一个不想敲redis命令的冲动,于是就开始设计这款Redis图形化客户端。那么这次有人肯定会问我,Redis客户端有那么多,为什么不直接用,而要浪费时间去开发一个呢?关于此问题我的答案是:我有那个实力!

哈哈哈,当然不是这个原因,真实原因是市面上的Redis客户端大多很丑陋,只提供了图形来展示信息功能弱,而实现一个Redis客户端也用不了多少代码,于是才做的此决定。

下载地址

  • 软件支持Windwos 版本、Mac版本
  • 下载地址:bg-boom-ui

软件特点

  • 纯Java开发
  • 免费使用
  • 支持Redis 图形化操作String、Hash、Set、ZSet、List的操作
  • 支持Redis客户端命令行操作,并带有输入提示
  • 支持Redis的慢指令监控
  • 支持Redis执行的指令,逆监控
  • 支持自动识别单机或集群操作,简化了集群客户端的使用方式
  • 当然还有很重要的是支持美轮美奂的皮肤功能

软件截图

实现原理

软件是用纯Java实现的,底层并没有使用Netty去与redis通信,而是使用Jedis直接实现,其核心的实现代码不足两百行:

package com.madou.dbtool.redis.manager;

import com.madou.common.annotation.HideClass;
import com.madou.dbtool.language.redis.parser.RedisContentTypeParser;
import com.madou.inters.util.TipUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisMonitor;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.params.ScanParams;
import redis.clients.jedis.resps.ScanResult;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @author miukoo
 * Redis 直连客户端
 */
@HideClass("directRedisSourceManager")
public class DirectRedisSourceManager implements RedisSourceManager {
    String host;
    int port;
    Jedis jedis;
    String password;
    // 标记是否为集群
    boolean cluster=false;
    // 集群连接器
    ClusterRedisSourceManager clusterRedisSourceManager;

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

    private synchronized Jedis connection(){
        if(jedis==null||!jedis.isConnected()) {
            try {
                jedis = new Jedis(host, port);
                if (password != null && password != "") {
                    jedis.auth(password);
                }
                jedis.info();
            }catch (Exception e){
                TipUtils.showErrorDialog("连接失败:"+e.getMessage(),"Tips");
            }
        }
        return  jedis;
    }

    @Override
    public int getDBCount() {
        connection();
        return Integer.parseInt(jedis.configGet("databases").get(1));
    }

    @Override
    public boolean isCluster() {
        return cluster;
    }

    @Override
    public List<RedisNodeInfo> getNodes() {
        connection();
        String info = jedis.info();
        List<RedisNodeInfo> list = new ArrayList<>();
        if(info.contains("cluster_enabled:1")){
            cluster=true;
            ClusterRedisSourceManager clusterRedisSourceManager = new ClusterRedisSourceManager(host,port,password);
            String[] nodes = jedis.clusterNodes().split("\n");
            for (String node : nodes) {
                String tmp[] = node.split(" ");
                String addr[] = tmp[1].split("@");
                RedisNodeInfo redisNodeInfo = new RedisNodeInfo();
                redisNodeInfo.setIp(addr[0].split(":")[0]);
                redisNodeInfo.setPort(Integer.valueOf(addr[0].split(":")[1]));
                redisNodeInfo.setRole(tmp[2]);
                if(redisNodeInfo.getIp().equals(host)&&redisNodeInfo.getPort()==port){
                    redisNodeInfo.setRedisSourceManager(new ClusterRedisSourceManager(host,port,password,this));
                }else {
                    redisNodeInfo.setRedisSourceManager(new ClusterRedisSourceManager(redisNodeInfo.getIp(),redisNodeInfo.getPort(),password));
                }
                list.add(redisNodeInfo);
            }
        }else {
            RedisNodeInfo redisNodeInfo = new RedisNodeInfo();
            redisNodeInfo.setIp(host);
            redisNodeInfo.setPort(port);
            redisNodeInfo.setRedisSourceManager(this);
            list.add(redisNodeInfo);
        }
        return list;
    }

    @Override
    public Long getDBSize(int index) {
        connection();
        jedis.select(index);
        return jedis.dbSize();
    }

    /**
     * 获取第一页的数据
     * @return
     */
    @Override
    public List<String> getFirst(int index) {
        connection();
        jedis.select(index);
        return jedis.scan("").getResult();
    }

    /**
     * 执行命令
     * @param commandText
     * @return
     */
    @Override
    public Object execute(int index,String commandText){
        connection();
        if(index>=0) {
            jedis.select(index);
        }
        String[] temp = commandText.trim().split(" ");
        Protocol.Command command = Protocol.Command.valueOf(temp[0].toUpperCase(Locale.ROOT));
        List<String> args = new ArrayList<>();
        for (int i = 1; i < temp.length; i++) {
            if(temp[i]!=""&&temp[i]!=" "){
                args.add(temp[i]);
                if(i==1) {
                    RedisContentTypeParser.redisKeywordTrieLoader.addWord(temp[i]);
                }
            }
        }
        String[] commandArgs = new String[args.size()];
        args.toArray(commandArgs);
        if(commandText.length()<20){
            RedisContentTypeParser.redisKeywordTrieLoader.addWord(commandText);
        }
        return jedis.sendCommand(command, commandArgs);
    }

    /**
     * 开启监控
     * @param jedisMonitor
     * @return
     */
    @Override
    public void monitor(JedisMonitor jedisMonitor){
        connection();
        jedis.monitor(jedisMonitor);
    }

    @Override
    public RedisSourceManager cloneDirect() {
        return new DirectRedisSourceManager(host,port,password);
    }

    @Override
    public RedisSourceManager cloneCluster() {
        return cloneDirect();
    }

    @Override
    public void close() {
        if(jedis!=null){
            jedis.disconnect();
            jedis.close();
            jedis = null;
        }
    }

}