Jedis直接使用Redis原生命令操作Redis,解决某些命令没有封装

背景:做项目中需要通过客户端ID关闭客户端连接(对应命令client kill id 12345),但是使用jedis封装的clientKill方法,尝试了很多次,都没有效果。所以就尝试使用反射方式,直接执行Redis命令来解决该问题。

使用Jedis的Connection类直接执行Redis命令

import redis.clients.jedis.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        try (Connection connection = new Connection("127.0.0.1") /*1.使用Connection连接Redis*/) {
            // 2. 通过反射获取Connection中的sendCommand方法(protected Connection sendCommand(Command cmd, String... args))。
            Method method = Connection.class.getDeclaredMethod("sendCommand", Protocol.Command.class, String[].class);
            method.setAccessible(true); // 设置可以访问private和protected方法
            // 3. 调用connection的sendCommand方法,第二个参数为执行的命令(比如set,get,client等),第三个参数为命令的参数。
            // 3.1 该命令最终对应redis中为: set test-key test-value
            method.invoke(connection, Protocol.Command.SET, new String[]{"test-key", "test-value"});
			// 4.获取Redis的命令执行结果
            System.out.println(connection.getBulkReply());
        }

    }

}

到Redis中查看

127.0.0.1:6379> get test-key
"test-value"

其中需要注意的点

  1. Protocol.Command 为一个枚举,redis的命令从这里面找,比如set,get,client等

  2. connection.getBulkReply() 可以获取到执行结果。获取的结果和使用redis-cli效果一样
    除了这个之外, 还有其他的,如果connection.getIntegerReply()。 具体使用哪一个,需要根据命令来决定。
    如果使用的不对,则会抛出类型转换异常。

封装成工具方法

    public static List execRedisCommand(Jedis jedis, String command, String... args) throws InvocationTargetException, IllegalAccessException {
        Protocol.Command cmd = Protocol.Command.valueOf(command.toUpperCase());
        Client client = jedis.getClient();
        Method  method = MethodUtils.getMatchingMethod(Client.class, "sendCommand", Protocol.Command.class, String[].class);
        method.setAccessible(true);
        method.invoke(client, cmd, args);
        try {
            List respList = new ArrayList<>();
            Object response = client.getOne();
            if (response instanceof List) {
                for (Object itemResp : ((List) response)) {
                    respList.add(new String((byte[]) itemResp));
                }
                return respList;
            } else {
                return Collections.singletonList(new String((byte[]) response));
            }

        } catch (JedisException e) {
            return Collections.singletonList(e.getMessage());
        }
    }

调用样例

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.auth("mypass");
System.out.println(execRedisCommand(jedis, "set23", "hello", "123").get(0));

maven



	org.apache.commons
	commons-lang3
	3.9

你可能感兴趣的:(Redis)