中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring boot cache redis 簡單理解自定義 KeyGenerator

發布時間:2020-07-02 05:49:07 來源:網絡 閱讀:5112 作者:北極冷冷冷 欄目:編程語言

簡單理解自定義 KeyGenerator

一般情況我們在 spring boot 中會使用 redis 作為緩存 但我們是需要自定義 cache key 的生成方式
1.為什么不使用 spring 默認的 生成策略?
先看看源碼:

public class DefaultKeyGenerator implements KeyGenerator {
        public static final int NO_PARAM_KEY = 0;
        public static final int NULL_PARAM_KEY = 53;

        public DefaultKeyGenerator() {
        }

        public Object generate(Object target, Method method, Object... params) {
                if (params.length == 0) {
//沒有參數直接返回 0
                        return 0;
                } else {
                        if (params.length == 1) {
                                Object param = params[0];
                                if (param == null) {
//有一個參數 并且為 null 返回 53
                                        return 53;
                                }
//參數不是數組 直接返回參數
                                if (!param.getClass().isArray()) {
                                        return param;
                                }
                        }
//其它情況 返回 深度計算的 hashcode  簡單理解可以認為就是一個 hashcode
                        return Arrays.deepHashCode(params);
                }
        }
}

DefaultKeyGenerator 最終返回的 緩存鍵值當參數列表的值相同時是一樣的 這樣就會造成獲取到錯誤的緩存數據

spring 還有一個 生成策略 同樣也是有這樣的 問題

public class SimpleKeyGenerator implements KeyGenerator {

     @Override
     public Object generate(Object target, Method method, Object... params) {
            return generateKey(params);
     }

     /**
        * Generate a key based on the specified parameters.
        */
     public static Object generateKey(Object... params) {
            if (params.length == 0) {
                 return SimpleKey.EMPTY;
            }
            if (params.length == 1) {
                 Object param = params[0];
                 if (param != null && !param.getClass().isArray()) {
                        return param;
                 }
            }
            return new SimpleKey(params);
     }

}

public class SimpleKey implements Serializable {

     public static final SimpleKey EMPTY = new SimpleKey();

     private final Object[] params;
     private final int hashCode;

     /**
        * Create a new {@link SimpleKey} instance.
        * @param elements the elements of the key
        */
     public SimpleKey(Object... elements) {
            Assert.notNull(elements, "Elements must not be null");
            this.params = new Object[elements.length];
            System.arraycopy(elements, 0, this.params, 0, elements.length);
            this.hashCode = Arrays.deepHashCode(this.params);
     }

     @Override
     public boolean equals(Object obj) {
            return (this == obj || (obj instanceof SimpleKey
                        && Arrays.deepEquals(this.params, ((SimpleKey) obj).params)));
     }

     @Override
     public final int hashCode() {
            return this.hashCode;
     }

     @Override
     public String toString() {
            return getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";
     }

}

最后 cache key 使用的是這個

return getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";

這也會在一定的情況下出現獲取到錯誤的緩存數據

所以我們需要自己自定義 cache key 的生成方式
我一般是這樣用的 類名+方法名+參數列表的類型+參數值 再做 哈希散列 作為key

@Bean
public KeyGenerator myKeyGenerator(){
     return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                 StringBuilder sb = new StringBuilder();
                 sb.append(target.getClass().getName());
                 sb.append(method.getName());
                 sb.append("&");
                 for (Object obj : params) {
                        if (obj != null){
                             sb.append(obj.getClass().getName());
                             sb.append("&");
                             sb.append(JSON.toJSONString(obj));
                             sb.append("&");
                        }
                 }
                 log.info("redis cache key str: "+sb.toString());

                 log.info("redis cache key sha256Hex: "+DigestUtils.sha256Hex(sb.toString()));
                 return DigestUtils.sha256Hex(sb.toString());
            }
     };
}
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

和平县| 资阳市| 山丹县| 三门峡市| 涪陵区| 中宁县| 贵定县| 阳新县| 鄂托克旗| 彩票| 隆昌县| 汝州市| 太仓市| 江孜县| 武汉市| 崇左市| 碌曲县| 长沙县| 始兴县| 沙田区| 上饶县| 博兴县| 万山特区| 迭部县| 乐东| 东丽区| 仙居县| 鹤峰县| 太康县| 宣城市| 丰宁| 博白县| 高青县| 绍兴县| 新绛县| 河东区| 濮阳市| 五台县| 沙洋县| 灯塔市| 宜良县|