1、首先引入msgpack所需要的包
<dependency> <groupId>org.msgpack</groupId> <artifactId>msgpack-core</artifactId> <version>0.8.13</version> </dependency> <dependency> <groupId>org.msgpack</groupId> <artifactId>jackson-dataformat-msgpack</artifactId> <version>0.8.13</version> </dependency>
2、新建RedisConfig.java (spring boot redis配置类)
import com.fasterxml.jackson.databind.ObjectMapper; import org.msgpack.jackson.dataformat.MessagePackFactory; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.*; @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { /** * 设置spring redis data 序列化模板 * @param factory * @return */ @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); Jackson2JsonRedisSerializer Jackson2Serializer = new Jackson2JsonRedisSerializer(Object.class); Jackson2Serializer.setObjectMapper(mapper); RedisSerializer redisSerializer= Jackson2Serializer; template.setValueSerializer(redisSerializer); template.setKeySerializer(new StringRedisSerializer()); return template; } /** * * 整合spring cache * 设置@cacheable 序列化方式 * * @return */ @Bean public RedisCacheConfiguration redisCacheConfiguration() { RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericMsgpackRedisSerializer())); return configuration; } }
3、新建GenericMsgpackRedisSerializer.java (整合spring cache msgpack序列化类)
import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; import org.msgpack.core.annotations.Nullable; import org.msgpack.jackson.dataformat.MessagePackFactory; import org.springframework.cache.support.NullValue; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import org.springframework.util.Assert; import org.springframework.util.StringUtils; public class GenericMsgpackRedisSerializer implements RedisSerializer<Object> { static final byte[] EMPTY_ARRAY = new byte[0]; private final ObjectMapper mapper; public GenericMsgpackRedisSerializer() { this.mapper = new ObjectMapper(new MessagePackFactory()); this.mapper.registerModule((new SimpleModule()).addSerializer(new GenericMsgpackRedisSerializer.NullValueSerializer(null))); this.mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY); } @Override public byte[] serialize(@Nullable Object source) throws SerializationException { if (source == null) { return EMPTY_ARRAY; } else { try { return this.mapper.writeValueAsBytes(source); } catch (JsonProcessingException var3) { throw new SerializationException("Could not write JSON: " + var3.getMessage(), var3); } } } @Override public Object deserialize(@Nullable byte[] source) throws SerializationException { return this.deserialize(source, Object.class); } @Nullable public <T> T deserialize(@Nullable byte[] source, Class<T> type) throws SerializationException { Assert.notNull(type, "Deserialization type must not be null! Pleaes provide Object.class to make use of Jackson2 default typing."); if (source == null || source.length == 0) { return null; } else { try { return this.mapper.readValue(source, type); } catch (Exception var4) { throw new SerializationException("Could not read JSON: " + var4.getMessage(), var4); } } } private class NullValueSerializer extends StdSerializer<NullValue> { private static final long serialVersionUID = 2199052150128658111L; private final String classIdentifier; NullValueSerializer(@Nullable String classIdentifier) { super(NullValue.class); this.classIdentifier = StringUtils.hasText(classIdentifier) ? classIdentifier : "@class"; } @Override public void serialize(NullValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeStartObject(); jgen.writeStringField(this.classIdentifier, NullValue.class.getName()); jgen.writeEndObject(); } } }
4、新建RedisCacheRedisUtils.java (序列化工具类)
package cn.ffast.core.redis; import java.util.Set; import com.fasterxml.jackson.databind.ObjectMapper; import org.msgpack.jackson.dataformat.MessagePackFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.*; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * @description: redis缓存工具类 * @copyright: * @createTime: 2017/11/13 15:23 * @author:dzy * @version:1.0 */ @Component public class RedisCacheUtils { private static Logger logger = LoggerFactory.getLogger(RedisCacheUtils.class); private final static Boolean REDIS_ENABLE = true; @Resource private RedisTemplate redisTemplate; @Resource RedisConnectionFactory redisConnectionFactory; public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } public RedisCacheUtils(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } /** * 缓存基本的对象,Integer、String、实体类等 * * @param key 缓存的键值 * @param value 缓存的值 * @return缓存的对象 */ public boolean setCacheObject(String key, Object value) { if (!REDIS_ENABLE) { return false; } logger.debug("存入缓存 key:" + key); try { ValueOperations<String, Object> operation = redisTemplate.opsForValue(); operation.set(key, value); return true; } catch (Exception ex) { logger.error(ex.getMessage()); return false; } } /** * 根据pattern匹配清除缓存 * * @param pattern */ public void clear(String pattern) { if (!REDIS_ENABLE) { return; } logger.debug("清除缓存 pattern:" + pattern); try { ValueOperations<String, Object> valueOper = redisTemplate.opsForValue(); RedisOperations<String, Object> redisOperations = valueOper.getOperations(); redisOperations.keys(pattern); Set<String> keys = redisOperations.keys(pattern); for (String key : keys) { redisOperations.delete(key); } } catch (Exception ex) { logger.error(ex.getMessage()); return; } } /** * 根据key清除缓存 * * @param key */ public void delete(String key) { if (!REDIS_ENABLE) { return; } logger.debug("删除缓存 key:" + key); try { ValueOperations<String, Object> valueOper = redisTemplate.opsForValue(); RedisOperations<String, Object> redisOperations = valueOper.getOperations(); redisOperations.delete(key); } catch (Exception ex) { logger.error(ex.getMessage()); return; } } /** * 获得缓存的基本对象。 * * @param key 缓存键值 * @return 缓存键值对应的数据 * */ public Object getCacheObject(String key) { if (!REDIS_ENABLE) { return null; } logger.debug("获取缓存 key:" + key); try { ValueOperations<String, Object> operation = redisTemplate.opsForValue(); return operation.get(key); } catch (Exception ex) { logger.error(ex.getMessage()); return null; } } /** * 获得缓存的基本对象。 * * @param key 缓存键值 * @return 缓存键值对应的数据 * */ public <T> T getCacheObject(String key, Class<T> clazz) { if (!REDIS_ENABLE) { return null; } logger.debug("获取缓存 key:" + key); RedisTemplate template = new StringRedisTemplate(redisConnectionFactory); Jackson2JsonRedisSerializer Jackson2Serializer = new Jackson2JsonRedisSerializer(clazz); Jackson2Serializer.setObjectMapper(new ObjectMapper(new MessagePackFactory())); RedisSerializer redisSerializer = Jackson2Serializer; template.setValueSerializer(redisSerializer); try { ValueOperations<String, T> operation = template.opsForValue(); return (T) operation.get(key); } catch (Exception ex) { logger.error(ex.getMessage()); return null; } } }
5、启动spring boot 开始测试
测试Controller
@RestController public class TestController { @Resource RedisCacheUtils redisCacheUtils; @GetMapping("/getCache") public Object getCache() { List<String> result = redisCacheUtils.getCacheObject("list_cache", new ArrayList<HashMap<String, String>>().getClass()); return result; } @GetMapping("/setCache") public Object setCache() { List<Map> list = new ArrayList<>(); for (int i = 0; i < 100; i++) { Map map = new HashMap<String, String>(); map.put("id", i); map.put("name", "index=" + i); list.add(map); } return redisCacheUtils.setCacheObject("list_cache", list); } }
测试使用spring cache注解
(待补充...)
看一下缓存结果
大小1893字节
我们对比下用fastjson序列化的区别
字节为2781 比msgpack大了800多字节
再看下速度
用10000条数据测试(非专业测试结果,仅供参考)
排名结果 msgpack>fastJson>jackjson