使用了不到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;
}
}
}
相关文章
- pod(五):pod hook(pod钩子)和优雅的关闭nginx pod
- pod(四):pod的重启策略和生命周期
- Ubiquitous Religions
- HDU1213 How many tables
- 1111. 有效括号的嵌套深度
- Istio(十三):Istio项目实际案例——Online Boutique
- 最小生成树-普利姆(Prim)算法
- 最短路径-弗洛伊德(Floyd)算法
- Istio(十二):Istio问题排查
- 最短路径-迪杰斯特拉(Dijkstra)算法
- Istio(十一):向istio服务网格中引入虚拟机
- 哈夫曼树
- 树与森林
- Istio(十):istio多集群部署模式
- 克鲁斯卡尔算法(Kruskal算法)求最小生成树
- Istio(九):istio安全之授权
- Istio(八):istio安全之认证,启用mTLS
- 平衡二叉树详解
- P1536 村村通
- Istio(七):ServiceEntry,sidecar,Envoy Filter