Java ReidsTemplate 發送腳本給redis執行 簡單例子

redisTemplate可以發送一段腳本給redis,來調用redis的接口。

腳本準備

執行redis的腳本。對於腳本的學習可以參考官網的文章:https://redis.io/commands/eval

jar包準備

我們使用redisTemplate,它有發送執行腳本的接口(下面的代碼來自spring-data-redis-1.8.1.RELEASE版本):

    public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer, List<K> keys, Object... args) {
        return this.scriptExecutor.execute(script, argsSerializer, resultSerializer, keys, args);
    }

實例

這裏以執行zrange函數爲例,發送“希望執行zrange”的腳本讓redis去執行。

數據準備

先做個數據準備,在命令行中執行兩個語句來插入數據(注意千萬不要一起粘貼執行哦,分開執行):

zadd test 1 one
zadd test 8 eight

然後用zrange查詢下:

zrange test 0 3

結果:

ceshi:0>zrange test 0 3
 1)  "one"
 2)  "eight"

腳本準備

接下來在redis的控制檯執行下腳本:

eval "return redis.call(KEYS[1],KEYS[2],ARGV[1],ARGV[2])ceshi:0>" 2 zrange test 0 3

結果:

ceshi:0>eval "return redis.call(KEYS[1],KEYS[2],ARGV[1],ARGV[2])ceshi:0>" 2 zrange test 0 3
 1)  "one"
 2)  "eight"

沒問題,接下來就是java的事情了

java編程

這裏只粘貼重要代碼,至於redisTemplate如何配置創建對象,相信廣大的開發者朋友都會。

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;  

    public List<String> pageKeysByZrangeScript(String tableName, Long start, Long end) {
        String scriptStr = "return redis.call(KEYS[1],KEYS[2], KEYS[3], KEYS[4])";//這裏用了4個KEYS,不用ARGV了,你可以用。不過用了的話,就注意redisTemplate.execute調用的時候,注意給最後一個參數傳遞argv的數組
        List<String> keys = new ArrayList<>();
        keys.add("zrange");
        keys.add(tableName);
        keys.add(start + "");
        keys.add(end + "");

        RedisSerializer redisSerializer = new StringRedisSerializer();
        DefaultRedisScript<ArrayList<String>> defaultRedisScript = new DefaultRedisScript(scriptStr, ArrayList.class);
        ArrayList<String> result = redisTemplate.execute(defaultRedisScript, new Jackson2JsonRedisSerializer(ArrayList.class), redisSerializer,
                keys, new ArrayList<>());//這裏因爲用的4個KEYS,沒用ARGV,所以傳入一個空的ARGV的List

        System.out.println(result);

        return result;
    }

說明:

1. redisTemplate會將我們定義好的語句發送給redis,執行“”eval“”。

2. 這裏比較麻煩的是:

DefaultRedisScript的創建以及redisTemplate.execute執行的時候傳入的序列化和反序列化實例

     2.1 首先,因爲查詢的結果是一堆字符串的列表,因此這列DefaultRedisScript的類型爲List<String>

     2.2 然後,execute函數:

        2.2.1. 第一個參數是腳本,直接傳入即可。

        2.2.2. 第二個參數是我們傳入的數據的序列化器(比如,看上面我的代碼,keys對象不是一個String的list麼),我們轉入的是list,因此用類型爲ArrayList的Jackson2JsonRedisSerializer序列化器

        2.2.3. 第三個參數,是redis返回數據的序列化器,因爲我們返回的是一個元素爲String的list,因此這列傳入StringRedisSerializer實例,爲什麼是String而不是list的?原因源碼中是這樣解析的:

 protected <T> T deserializeResult(RedisSerializer<T> resultSerializer, Object result) {
        if (result instanceof byte[]) {
            return resultSerializer == null ? result : resultSerializer.deserialize((byte[])((byte[])result));
        } else if (!(result instanceof List)) {
            return result;
        } else {
            List results = new ArrayList();
            Iterator var4 = ((List)result).iterator();

            while(var4.hasNext()) {
                Object obj = var4.next();
                results.add(this.deserializeResult(resultSerializer, obj));
            }

            return results;
        }
    }

注意看,當Object result不是byte[]並且是List的時候,就會遍歷其中的每一個元素,用序列化器去反序列化每一個元素。因此,我們傳String的序列化器。

         2.2.4. 第四個參數,是我們的參數list,注意list中的參數對應 KEYS[1],KEYS[2], KEYS[3], KEYS[4] 的順序。

         2.2.5. 第五個參數,這個是腳本執行語法中的ARGV[N]的數據,我們這裏全部當做KEY來傳遞,因此全部寫爲KEYS,ARGV爲空的list(注意不能傳null!看源碼就知道了)。

完成

這樣就完成了基本的一個小例子。

看不懂的同學多半是卡在腳本的語法上了,注意仔細看官網文檔即可,這裏再粘貼出來官網地址:https://redis.io/commands/eval

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章