自定义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
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(); } }