SpringBoot2(十)自定義Cache


自定義Cache十分簡單,找到接口,實現它即可,難點是序列化的自動轉型問題。

 

前面一篇文章已經提到,自定義Cache中 get(Object key, Class<T> aClass) 函數從未被調用,無法用來對接JSON.parseObject(String json, Class<T> clazz) 函數。

雖然不理解作者的真實意圖,事實已然如此,那就只能嘗試解決,編碼過程中,需要想辦法保存Class的值。

方法一:

  改寫CacheInterceptor接口(位於context核心包下),雖然很簡單直接,但是Spring的回答也簡單粗暴:“不允許!”項目啟動直接報錯,強調不允許修改。

方法二:

  在Key上做文章,KeyGenerator接口需要實現 generate(Object target, Method method, Object... params) 接口,這里能拿到數據的全類名。

  但是這樣做依然不夠好,Key值不宜復雜設計,因為Key值用於數據檢索,不論基於何種技術實現,Key值越長,檢索必定越慢。

方法三:

  將全類名附加到Value中,這種做法,FastJSON對此作了支持,直接調用即可。值得注意的是,需要調用ParserConfig.getGlobalInstance()開啟白名單,標明哪些類可以自動轉型。

  public static void main(String[] args) {
    SysUser user = new SysUser();
    user.setUserNick("aaaaa");
    String str = JSON.toJSONString(user, FastJsonUtils.serializeConfig, SerializerFeature.WriteClassName);

    System.out.println(str);

    ParserConfig.getGlobalInstance().addAccept("cn.seaboot.admin.bean.");
    System.out.println(JSON.parse(str).getClass());
  }

 

自定義Cache簡單的實現:

CacheConfig

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;

/**
 * @author Mr.css
 * @date 2019/12/23
 */
@Configuration
public class CacheConfig extends CachingConfigurerSupport {

  @Bean
  @Override
  public CacheManager cacheManager() {
    return new RedisCacheManager();
  }
}

 CacheManager

import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractCacheManager;

import java.util.ArrayList;
import java.util.Collection;

public class RedisCacheManager extends AbstractCacheManager {

  @Override
  protected Collection<? extends Cache> loadCaches() {
    return new ArrayList<>();
  }

  @Override
  protected Cache getMissingCache(String name) {
    return new RedisCache();
  }
}

 Cache 

將下列代碼中的Map換成更有效的存儲結構,按照自己的想法進行設計即可

import cn.seaboot.admin.consts.SystemConst;
import cn.seaboot.common.core.Converter;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 *
 */
public class RedisCache implements Cache {

  Map<Object, Object> map = new HashMap<>();

  /**
   * 簡單直白,就是獲取Cache的名字
   */
  @Override
  public String getName() {
    return SystemConst.CACHE_DEF;
  }

  /**
   * 獲取底層的緩存實現對象
   */
  @Override
  public Object getNativeCache() {
    return SystemConst.CACHE_DEF;
  }

  /**
   * 根據鍵獲取值,把值包裝在ValueWrapper里面,如果有必要可以附加額外信息
   */
  @Override
  public ValueWrapper get(Object key) {
    System.out.println("ValueWrapper");
    return map.containsKey(key)?new SimpleValueWrapper(map.get(key)):null;
  }

  /**
   *
   */
  @Override
  public <T> T get(Object key, Class<T> aClass) {
    try {
      System.out.println("get(Object o, Class<T> aClass)");
      return map.containsKey(key)?Converter.convert(map.get(key), aClass):null;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 與sync屬性有關
   */
  @Override
  public <T> T get(Object key, Callable<T> valueLoader) {
    try {
      System.out.println("get");
      return valueLoader.call();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 存放鍵值對
   */
  @Override
  public void put(Object key, Object value) {
    System.out.println("put(Object key, Object value)");
    map.put(key, value);
  }

  /**
   * 如果鍵對應的值不存在,則添加鍵值對
   */
  @Override
  public ValueWrapper putIfAbsent(Object key, Object value) {
    System.out.println("putIfAbsent");
    map.put(key, value);
    return new SimpleValueWrapper(value);
  }

  /**
   * 移除鍵對應鍵值對
   */
  @Override
  public void evict(Object key) {
    System.out.println("evict");
    map.remove(key);
  }

  /**
   * 清空緩存
   */
  @Override
  public void clear() {
    System.out.println("clear");
    map.clear();
  }
}

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM