当前位置:   article > 正文

redis系列化JSON存取_redis 存 json java

redis 存 json java

系列化前通过redisTemplate.opsForHash().put进去的数据带有类信息

把redis数据系列化成JSON形式存取。

系列换成byte类型,不再带有类信息,节省空间。

一、新建redis配置

  1. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  2. import com.fasterxml.jackson.annotation.PropertyAccessor;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.fasterxml.jackson.databind.SerializationFeature;
  5. import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
  6. import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  10. import org.springframework.data.redis.core.RedisTemplate;
  11. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  12. import org.springframework.data.redis.serializer.StringRedisSerializer;
  13. /**
  14. * @author czmao
  15. * @Description RedisConfig
  16. * @since 2023/8/11 0:30
  17. */
  18. @Configuration
  19. public class RedisConfig {
  20. @Bean("orderRedisTemplate")
  21. public RedisTemplate<String, Object> baseRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {
  22. RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  23. redisTemplate.setConnectionFactory(redisConnectionFactory);
  24. //创建JSON序列化工具
  25. Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
  26. // 创建JSON序列化工具
  27. //GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  28. //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型
  29. ObjectMapper objectMapper = new ObjectMapper();
  30. //将当前对象的数据类型也存入序列化的结果字符串中,以便反序列化
  31. objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
  32. // 解决jackson2无法反序列化LocalDateTime的问题
  33. objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
  34. objectMapper.registerModule(new JavaTimeModule());
  35. objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  36. jsonRedisSerializer.setObjectMapper(objectMapper);
  37. //首先key的序列化方式
  38. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  39. redisTemplate.setKeySerializer(stringRedisSerializer);
  40. // 设置值的序列化器
  41. redisTemplate.setValueSerializer(jsonRedisSerializer);
  42. redisTemplate.afterPropertiesSet();
  43. return redisTemplate;
  44. }
  45. }

二、JSON 系列化接口

  1. import java.lang.reflect.Type;
  2. /**
  3. * @author czmao
  4. * @description CommonSerializer
  5. * @since 2023/9/19 21:59
  6. */
  7. public interface CommonSerializer {
  8. byte[] serialize(Type var1, Object var2);
  9. Object deserialize(byte[] var1, Type var2);
  10. }

系列化和反系列化的JSON要持一致 这里选择fastjson,可以根据实际情况选择

  1. import com.alibaba.fastjson.JSON;
  2. import com.vanchan.sca.order.service.CommonSerializer;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.stereotype.Component;
  7. import java.lang.reflect.Type;
  8. import java.nio.charset.Charset;
  9. /**
  10. * @author czmao
  11. * @Description CommonJacksonSerializer
  12. * @since 2023/9/19 22:00
  13. */
  14. @Component
  15. public class CommonJacksonSerializer implements CommonSerializer {
  16. private static final Logger LOGGER = LoggerFactory.getLogger(CommonJacksonSerializer.class);
  17. public static final Charset DEFAULT_CHARSET_INSTANCE = Charset.forName("UTF-8");
  18. public CommonJacksonSerializer() {
  19. }
  20. @Override
  21. public byte[] serialize(Type var1, Object ob) {
  22. if (ob == null) {
  23. return new byte[0];
  24. } else {
  25. String result = JSON.toJSONString(ob);
  26. return StringUtils.isEmpty(result) ? new byte[0] : result.getBytes(DEFAULT_CHARSET_INSTANCE);
  27. }
  28. }
  29. @Override
  30. public Object deserialize(byte[] bytes, Type type) {
  31. try {
  32. return JSON.parseObject(new String(bytes), type);
  33. } catch (Exception var4) {
  34. LOGGER.error(var4.getMessage(), var4);
  35. return null;
  36. }
  37. }
  38. }

三、redis接口

  1. package com.vanchan.sca.order.service;
  2. import java.util.Collection;
  3. import java.util.List;
  4. import java.util.Map;
  5. import java.util.concurrent.TimeUnit;
  6. /**
  7. * @author czmao
  8. * @description redis系列化操作数据入口
  9. * @since 2023/9/19 14:39
  10. */
  11. public interface CommonRedisCacheService {
  12. /**
  13. * 普通类型String 推送
  14. *
  15. * @param var1
  16. * @param var2
  17. */
  18. <V> void put(String var1, V var2, Long expireTime, final TimeUnit unit);
  19. /**
  20. * String类型key 推送
  21. *
  22. * @param var1
  23. * @param var2
  24. */
  25. <V> void put(String var1, V var2);
  26. /**
  27. * String类型key 获取
  28. *
  29. * @param key key
  30. * @param clazz 对象r
  31. */
  32. <V> V get(String key, Class<V> clazz);
  33. /**
  34. * set数据读取一次读一个
  35. *
  36. * @param key
  37. * @param aClass
  38. * @return
  39. */
  40. <V> V setPop(String key, Class<V> aClass);
  41. /**
  42. * set数据添加(批量)
  43. *
  44. * @param key
  45. * @param clazz
  46. * @return
  47. */
  48. <V> Long setAddList(String key, List<V> clazz);
  49. /**
  50. * set数据添加
  51. *
  52. * @param key
  53. * @param clazz
  54. * @return
  55. */
  56. <V> Long setAdd(String key, V clazz);
  57. /**
  58. * LIST 左推数据
  59. *
  60. * @param key
  61. * @param clazz
  62. * @return
  63. */
  64. <V> Long listLeftPush(String key, V clazz);
  65. /**
  66. * redis-set数据左读取,一次读一个
  67. *
  68. * @param key
  69. * @param clazz
  70. * @return
  71. */
  72. <V> V listLeftPop(String key, Class<V> clazz);
  73. /**
  74. * LIST 右推数据
  75. *
  76. * @param key 键
  77. * @param clazz 对象
  78. * @return 影响条数
  79. */
  80. <V> Long lRightPush(String key, V clazz);
  81. /**
  82. * LIST 右读数据
  83. *
  84. * @param key 键
  85. * @param clazz 对象
  86. * @return 反系列化对象
  87. */
  88. <V> V lRightPop(String key, Class<V> clazz);
  89. /**
  90. * 判断list数量
  91. *
  92. * @param key
  93. * @return
  94. */
  95. <V> Long length(String key);
  96. /**
  97. * list类型数据查询 全量
  98. *
  99. * @param key
  100. * @param var2
  101. * @return
  102. */
  103. <V> List<V> getList(String key, Class<V> var2);
  104. /**
  105. * list类型数据查询 指定区间
  106. *
  107. * @param key key
  108. * @param start 开始
  109. * @param end 结束
  110. * @param clazz
  111. * @return
  112. */
  113. <V> List<V> getList(String key, int start, int end, Class<V> clazz);
  114. /**
  115. * 根据key查询hash类 所有数据
  116. *
  117. * @param mainKey
  118. * @param clazz
  119. * @return
  120. */
  121. <V> Map<String, V> hGetAll(String mainKey, Class<V> clazz);
  122. /**
  123. * 根据key-key精准查询hash类数据
  124. *
  125. * @param mainKey redis主key
  126. * @param field 副键
  127. * @param clazz 对象类型
  128. * @return
  129. */
  130. <V> V hGet(String mainKey, String field, Class<V> clazz);
  131. /**
  132. * 利用双key往hashMap添加数据
  133. *
  134. * @param key
  135. * @param field
  136. * @param var3
  137. */
  138. <V> void hPut(String key, String field, V var3);
  139. /**
  140. * 批量往hashMap添加数据
  141. *
  142. * @param key
  143. * @param var3
  144. * @param
  145. */
  146. <V> void hPutAll(String key, Map<String, V> var3);
  147. /**
  148. * 根据key获取hash所有value值 返回list
  149. *
  150. * @param key
  151. * @return
  152. * @Author: chenzumao
  153. */
  154. <V> List<V> hGetAllToList(String key, Class<V> clazz);
  155. /**
  156. * 删除hash指定数据
  157. *
  158. * @param key key
  159. * @param field field
  160. */
  161. <V> void hDel(String key, String field);
  162. /**
  163. * 根据key和多个field获取hash相应的value值 返回list
  164. *
  165. * @param key 主键key
  166. * @param fields 批量获取的副键
  167. * @param clazz 类
  168. * @return 集合
  169. * @Author: chenzumao
  170. */
  171. <V> List<V> hGetAllToList(String key, Collection<String> fields, Class<V> clazz);
  172. /**
  173. * 危险操作-删除该key所有数据
  174. *
  175. * @param key
  176. * @return
  177. */
  178. <V> Long delKey(String key);
  179. }

四、redis系列化实现类

  1. package com.vanchan.sca.order.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.vanchan.sca.order.service.CommonRedisCacheService;
  5. import com.vanchan.sca.order.service.CommonSerializer;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.collections4.CollectionUtils;
  8. import org.apache.commons.lang3.StringUtils;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.dao.DataAccessException;
  11. import org.springframework.data.redis.connection.RedisConnection;
  12. import org.springframework.data.redis.connection.RedisStringCommands;
  13. import org.springframework.data.redis.core.RedisCallback;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.data.redis.core.types.Expiration;
  16. import org.springframework.stereotype.Component;
  17. import javax.annotation.Resource;
  18. import java.lang.reflect.Type;
  19. import java.nio.charset.StandardCharsets;
  20. import java.util.*;
  21. import java.util.concurrent.TimeUnit;
  22. import java.util.stream.Collectors;
  23. /**
  24. * @author czmao
  25. * @Description redis系列化实现类
  26. * @since 2023/8/16 8:40
  27. */
  28. @Component(value = "orderRedisCacheService")
  29. @Slf4j
  30. public class CommonRedisCacheServiceImpl implements CommonRedisCacheService {
  31. @Resource(name = "orderRedisTemplate")
  32. private RedisTemplate<String, byte[]> redisTemplate;
  33. private ObjectMapper objectMapper;
  34. @Autowired
  35. private CommonSerializer serializer;
  36. public CommonRedisCacheServiceImpl() {
  37. super();
  38. this.objectMapper = new ObjectMapper();
  39. }
  40. /**
  41. * 系列化:将给定的对象序列化为JSON字节数组
  42. *
  43. * @param value
  44. * @return 数组
  45. */
  46. public byte[] serialize(Object value) {
  47. byte[] bytes = null;
  48. try {
  49. bytes = objectMapper.writeValueAsBytes(value);
  50. } catch (Exception e) {
  51. log.error("Failed to serialize and save data to Redis", e);
  52. }
  53. return bytes;
  54. }
  55. /**
  56. * 系列化List集合
  57. *
  58. * @param values
  59. * @return
  60. */
  61. byte[][] serializeValues(Collection<?> values) {
  62. byte[][] rawValues = new byte[values.size()][];
  63. int i = 0;
  64. Object value;
  65. for (Iterator<?> iterator = values.iterator(); iterator.hasNext(); rawValues[i++] = this.serialize(value)) {
  66. value = iterator.next();
  67. }
  68. return rawValues;
  69. }
  70. /**
  71. * 反系列化:从Redis中检索字节数组并将其反序列化为给定类型的对象
  72. *
  73. * @param data redis数据
  74. * @param valueType 转换对象
  75. * @return
  76. */
  77. public <V> V deserialize(byte[] data, Class<V> valueType) {
  78. if (data == null) {
  79. return null;
  80. }
  81. try {
  82. return (V) serializer.deserialize(data, valueType);
  83. } catch (Exception e) {
  84. log.error("Failed to retrieve and deserialize data from Redis", e);
  85. }
  86. return null;
  87. }
  88. /**
  89. * 系列化字符串
  90. *
  91. * @param value
  92. * @return
  93. */
  94. private byte[] serializeForString(String value) {
  95. return value == null ? null : value.getBytes(StandardCharsets.UTF_8);
  96. }
  97. /**
  98. * 获取指定变量中的value值
  99. *
  100. * @param key
  101. * @return
  102. * @Author: chenzumao
  103. */
  104. @Override
  105. public <V> List<V> hGetAllToList(String key, Class<V> clazz) {
  106. List<V> objectList = new ArrayList<>();
  107. byte[] keyBytes = serializeForString(key);
  108. if (this.hasKey(key)) {
  109. List<byte[]> dataBytes = this.redisTemplate.execute(connection -> connection.hVals(keyBytes), true);
  110. objectList = deserializeList(dataBytes, clazz);
  111. }
  112. return objectList;
  113. }
  114. /**
  115. * 根据key和多个field获取hash相应的value值 返回list
  116. *
  117. * @param key 主键key
  118. * @param fields 批量获取的副键
  119. * @param clazz 类
  120. * @return 集合
  121. * @Author: chenzumao
  122. */
  123. @Override
  124. public <V> List<V> hGetAllToList(String key, Collection<String> fields, Class<V> clazz) {
  125. List<V> objectList = new ArrayList<>();
  126. byte[] keyBytes = serializeForString(key);
  127. if (CollectionUtils.isEmpty(fields)) {
  128. return objectList;
  129. }
  130. List<String> collect = fields.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
  131. if (CollectionUtils.isEmpty(collect)) {
  132. return objectList;
  133. }
  134. byte[][] rawHashKeys = new byte[collect.size()][];
  135. int counter = 0;
  136. for (String hashKey : fields) {
  137. rawHashKeys[counter++] = serializeForString(hashKey);
  138. }
  139. if (this.hasKey(keyBytes)) {
  140. List<byte[]> dataBytes = this.redisTemplate.execute(connection -> connection.hMGet(keyBytes, rawHashKeys), true);
  141. objectList = deserializeList(dataBytes, clazz);
  142. }
  143. return objectList;
  144. }
  145. /**
  146. * List反系列化
  147. *
  148. * @param dataBytes 查询到的数据
  149. * @param clazz 类
  150. * @return
  151. */
  152. private <V> List<V> deserializeList(List<byte[]> dataBytes, Class<V> clazz) {
  153. List<V> dataList = new ArrayList<>();
  154. if (CollectionUtils.isEmpty(dataBytes)) {
  155. return dataList;
  156. } else {
  157. Iterator<byte[]> iterator = dataBytes.iterator();
  158. while (iterator.hasNext()) {
  159. byte[] next = iterator.next();
  160. if (null == next || next.length == 0) {
  161. continue;
  162. }
  163. V dataInfo = this.deserialize(next, clazz);
  164. if (null != dataInfo) {
  165. dataList.add(dataInfo);
  166. }
  167. }
  168. }
  169. return dataList;
  170. }
  171. <V extends Collection<?>> V deserializeValues(Collection<byte[]> rawValues, Class<?> collectionType, Class<V> type) {
  172. if (rawValues == null) {
  173. return (V) new ArrayList<>();
  174. } else {
  175. Collection<Object> values = List.class.isAssignableFrom(collectionType) ? new ArrayList<>(rawValues.size()) : new LinkedHashSet<>(rawValues.size());
  176. Iterator<byte[]> var5 = rawValues.iterator();
  177. while (var5.hasNext()) {
  178. byte[] bs = var5.next();
  179. values.add(this.deserialize(bs, type));
  180. }
  181. return (V) values;
  182. }
  183. }
  184. /**
  185. * 把value系列化存byte
  186. *
  187. * @param value
  188. * @param <V>
  189. * @return
  190. */
  191. private <V> byte[] serializeToString(V value) {
  192. return null == value ? new byte[0] : this.serializer.serialize((Type) null, value);
  193. }
  194. /**
  195. * 基本类型数据操作
  196. *
  197. * @param key key
  198. * @param value value byte
  199. * @param expireSec 过期时间 毫秒
  200. */
  201. private void doPut(String key, final byte[] value, final long expireSec) {
  202. final byte[] keyBytes = this.serializeForString(key);
  203. this.redisTemplate.execute(new RedisCallback<Object>() {
  204. public String doInRedis(RedisConnection connection) throws DataAccessException {
  205. if (expireSec > 0L) {
  206. connection.set(keyBytes, value, Expiration.milliseconds(expireSec), RedisStringCommands.SetOption.UPSERT);
  207. } else {
  208. connection.set(keyBytes, value);
  209. }
  210. return null;
  211. }
  212. });
  213. }
  214. /**
  215. * 普通类型String 推送
  216. *
  217. * @param key key
  218. * @param var2 value
  219. */
  220. @Override
  221. public <V> void put(String key, V var2, Long expireTime, final TimeUnit unit) {
  222. byte[] valueBytes = serializeToString(var2);
  223. long time = 0;
  224. if (null != expireTime) {
  225. time = unit.toMillis(expireTime);
  226. }
  227. this.doPut(key, valueBytes, time);
  228. }
  229. /**
  230. * 普通类型String 推送
  231. *
  232. * @param key key
  233. * @param var2 value
  234. */
  235. @Override
  236. public <V> void put(String key, V var2) {
  237. byte[] valueBytes = serializeToString(var2);
  238. this.doPut(key, valueBytes, 0);
  239. }
  240. @Override
  241. public <V> V get(String key, Class<V> clazz) {
  242. byte[] byteValue = this.doGet(key);
  243. return byteValue == null ? null : deserialize(byteValue, clazz);
  244. }
  245. private byte[] doGet(final String key) {
  246. byte[] bytes = serializeForString(key);
  247. return this.redisTemplate.execute(new RedisCallback<byte[]>() {
  248. public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
  249. return connection.get(bytes);
  250. }
  251. });
  252. }
  253. /**
  254. * set数据读取一次读一个
  255. *
  256. * @param key
  257. * @param clazz
  258. * @return
  259. */
  260. @Override
  261. public <V> V setPop(String key, Class<V> clazz) {
  262. final byte[] keyBytes = this.serializeForString(key);
  263. byte[] hGetBytes = this.redisTemplate.execute(connection -> connection.sPop(keyBytes), true);
  264. return this.deserialize(hGetBytes, clazz);
  265. }
  266. /**
  267. * set数据添加(批量)
  268. *
  269. * @param key
  270. * @param values 对象集合
  271. * @return 影响条数
  272. */
  273. @Override
  274. public <V> Long setAddList(String key, List<V> values) {
  275. byte[][] listBytes = this.serializeValues(values);
  276. final byte[] keyBytes = this.serializeForString(key);
  277. return this.redisTemplate.execute(new RedisCallback<Long>() {
  278. @Override
  279. public Long doInRedis(RedisConnection connection) throws DataAccessException {
  280. return connection.sAdd(keyBytes, listBytes);
  281. }
  282. });
  283. }
  284. /**
  285. * set数据添加
  286. *
  287. * @param key 键
  288. * @param value 对象
  289. * @return 影响条数
  290. */
  291. @Override
  292. public <V> Long setAdd(String key, V value) {
  293. byte[] valueByte = this.serialize(value);
  294. final byte[] keyBytes = this.serializeForString(key);
  295. return this.redisTemplate.execute(new RedisCallback<Long>() {
  296. @Override
  297. public Long doInRedis(RedisConnection connection) throws DataAccessException {
  298. return connection.sAdd(keyBytes, valueByte);
  299. }
  300. });
  301. }
  302. /**
  303. * LIST 左推数据
  304. *
  305. * @param key 键
  306. * @param value 对象
  307. * @return 影响条数
  308. */
  309. @Override
  310. public <V> Long listLeftPush(String key, V value) {
  311. byte[] valBytes = this.serialize(value);
  312. byte[] keyBytes = this.serializeForString(key);
  313. return this.redisTemplate.execute(new RedisCallback<Long>() {
  314. @Override
  315. public Long doInRedis(RedisConnection connection) throws DataAccessException {
  316. return connection.lPush(keyBytes, valBytes);
  317. }
  318. });
  319. }
  320. /**
  321. * LIST 左读数据
  322. *
  323. * @param key 键
  324. * @param clazz 对象
  325. * @return 反系列化对象
  326. */
  327. @Override
  328. public <v> v listLeftPop(String key, Class<v> clazz) {
  329. final byte[] keyBytes = this.serializeForString(key);
  330. byte[] hGetBytes = this.redisTemplate.execute(connection -> connection.lPop(keyBytes), true);
  331. return this.deserialize(hGetBytes, clazz);
  332. }
  333. /**
  334. * LIST 右推数据
  335. *
  336. * @param key 键
  337. * @param value 对象
  338. * @return 影响条数
  339. */
  340. @Override
  341. public <V> Long lRightPush(String key, V value) {
  342. byte[] valBytes = this.serialize(value);
  343. byte[] keyBytes = this.serializeForString(key);
  344. return this.redisTemplate.execute(new RedisCallback<Long>() {
  345. @Override
  346. public Long doInRedis(RedisConnection connection) throws DataAccessException {
  347. return connection.rPush(keyBytes, valBytes);
  348. }
  349. });
  350. }
  351. /**
  352. * LIST 右读数据
  353. *
  354. * @param key 键
  355. * @param clazz 对象
  356. * @return 反系列化对象
  357. */
  358. @Override
  359. public <V> V lRightPop(String key, Class<V> clazz) {
  360. final byte[] keyBytes = this.serializeForString(key);
  361. byte[] hGetBytes = this.redisTemplate.execute(connection -> connection.rPop(keyBytes), true);
  362. return this.deserialize(hGetBytes, clazz);
  363. }
  364. @Override
  365. public Long length(String key) {
  366. final byte[] keyBytes = this.serializeForString(key);
  367. return this.redisTemplate.execute(connection -> connection.lLen(keyBytes), true);
  368. }
  369. public <V> List<V> getList(String key, Class<V> clazz) {
  370. int begin = 0;
  371. int end = Integer.MAX_VALUE;
  372. return this.getList(key, begin, end, clazz);
  373. }
  374. /**
  375. * 指定查询区间
  376. *
  377. * @param key
  378. * @param begin
  379. * @param end
  380. * @param clazz
  381. * @return
  382. */
  383. @Override
  384. public <V> List<V> getList(String key, final int begin, final int end, final Class<V> clazz) {
  385. List<V> valueList = new ArrayList<>();
  386. try {
  387. final byte[] keyBytes = this.serializeForString(key);
  388. List<byte[]> valueBytes = this.redisTemplate.execute(connection -> connection.lRange(keyBytes, begin, end), true);
  389. if (CollectionUtils.isEmpty(valueBytes)) {
  390. return valueList;
  391. }
  392. Iterator<byte[]> iterator = valueBytes.iterator();
  393. while (iterator.hasNext()) {
  394. byte[] next = iterator.next();
  395. valueList.add(deserialize(next, clazz));
  396. }
  397. } catch (Exception var6) {
  398. log.error(var6.getMessage(), var6);
  399. return valueList;
  400. }
  401. return valueList;
  402. }
  403. /**
  404. * HASH反系列化
  405. *
  406. * @param entries
  407. * @param clazz
  408. * @return
  409. */
  410. private <V> Map<String, V> deserializeMap(Map<byte[], byte[]> entries, Class<V> clazz) {
  411. if (entries == null) {
  412. return new HashMap<>(0);
  413. } else {
  414. Map<String, V> map = new LinkedHashMap<>(entries.size());
  415. Iterator<?> var4 = entries.entrySet().iterator();
  416. while (var4.hasNext()) {
  417. Map.Entry<byte[], byte[]> entry = (Map.Entry) var4.next();
  418. map.put(entry.getKey() == null ? null : new String(entry.getKey()), this.deserialize(entry.getValue(), clazz));
  419. }
  420. return map;
  421. }
  422. }
  423. /**
  424. * 序列Map key和value
  425. *
  426. * @param originalMap
  427. * @return
  428. * @throws Exception
  429. */
  430. private <V> Map<byte[], byte[]> serializeMap(Map<String, V> originalMap) {
  431. Map<byte[], byte[]> serializedMap = new HashMap<>();
  432. try {
  433. for (Map.Entry<String, V> entry : originalMap.entrySet()) {
  434. byte[] keyBytes = entry.getKey().getBytes();
  435. byte[] valueBytes;
  436. if (entry.getValue() instanceof String) {
  437. valueBytes = entry.getValue().toString().getBytes();
  438. } else if (entry.getValue() instanceof Integer) {
  439. valueBytes = Integer.toString((Integer) entry.getValue()).getBytes();
  440. } else if (entry.getValue() instanceof Long) {
  441. valueBytes = Long.toString((Long) entry.getValue()).getBytes();
  442. } else if (entry.getValue() instanceof Double) {
  443. valueBytes = Double.toString((Double) entry.getValue()).getBytes();
  444. } else if (entry.getValue() instanceof Float) {
  445. valueBytes = Float.toString((Float) entry.getValue()).getBytes();
  446. } else {
  447. if (entry.getValue() != null) {
  448. valueBytes = JSON.toJSONBytes(entry.getValue());
  449. } else {
  450. log.error("serializeMap -->Unsupported value type");
  451. continue;
  452. }
  453. }
  454. serializedMap.put(keyBytes, valueBytes);
  455. }
  456. } catch (Exception e) {
  457. log.error("serializeMap error ", e);
  458. }
  459. return serializedMap;
  460. }
  461. /**
  462. * 根据key查询hash类所有数据
  463. *
  464. * @param key
  465. * @param clazz
  466. * @return
  467. */
  468. @Override
  469. public <V> Map<String, V> hGetAll(String key, Class<V> clazz) {
  470. final byte[] keyBytes = this.serializeForString(key);
  471. if (this.hasKey(keyBytes)) {
  472. Map<byte[], byte[]> entries = this.redisTemplate.execute(connection -> connection.hGetAll(keyBytes), true);
  473. return this.deserializeMap(entries, clazz);
  474. } else {
  475. log.warn("没有找到【{}】的数据", key);
  476. return new HashMap<>();
  477. }
  478. }
  479. /**
  480. * 根据key-key精准查询hash类数据
  481. *
  482. * @param key redis主key
  483. * @param field 副键
  484. * @param clazz 对象类型
  485. * @return
  486. */
  487. @Override
  488. public <V> V hGet(String key, String field, Class<V> clazz) {
  489. V hashData = null;
  490. try {
  491. final byte[] keyBytes = this.serializeForString(key);
  492. if (this.hasKey(keyBytes)) {
  493. final byte[] fileIdBytes = this.serializeForString(field);
  494. byte[] hGetBytes = this.redisTemplate.execute(connection -> connection.hGet(keyBytes, fileIdBytes), true);
  495. if (hGetBytes != null) {
  496. hashData = deserialize(hGetBytes, clazz);
  497. }
  498. }
  499. } catch (Exception var6) {
  500. log.error(var6.getMessage(), var6);
  501. }
  502. return hashData;
  503. }
  504. @Override
  505. public <V> void hPut(String key, String field, V value) {
  506. try {
  507. final byte[] keyBytes = this.serializeForString(key);
  508. final byte[] hKeyBytes = this.serializeForString(field);
  509. final byte[] valBytes = this.serialize(value);
  510. this.redisTemplate.execute(new RedisCallback<Boolean>() {
  511. @Override
  512. public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
  513. return connection.hSet(keyBytes, hKeyBytes, valBytes);
  514. }
  515. });
  516. } catch (Exception e) {
  517. log.error("往hash存放数据失败【{}】【{}】,原因", key, field, e);
  518. }
  519. }
  520. @Override
  521. public <V> void hPutAll(String key, Map<String, V> value) {
  522. try {
  523. final byte[] keyBytes = this.serializeForString(key);
  524. Map<byte[], byte[]> serializeMap = this.serializeMap(value);
  525. if (!serializeMap.isEmpty()) {
  526. this.redisTemplate.execute(new RedisCallback<Object>() {
  527. @Override
  528. public Object doInRedis(RedisConnection connection) throws DataAccessException {
  529. connection.hMSet(keyBytes, serializeMap);
  530. return null;
  531. }
  532. });
  533. } else {
  534. log.warn("没有【{}】系列化后的数据,不执行存储", key);
  535. }
  536. } catch (Exception e) {
  537. log.error("往hash存放数据失败【{}】,原因", key, e);
  538. }
  539. }
  540. @Override
  541. public void hDel(String key, String hKey) {
  542. this.redisTemplate.opsForHash().delete(key, hKey);
  543. }
  544. /**
  545. * @param key key值
  546. * @return 是否存在
  547. * @Description: 是否存在当前key
  548. * @Author: chenzumao
  549. */
  550. public boolean hasKey(String key) {
  551. if (StringUtils.isBlank(key)) {
  552. return false;
  553. }
  554. return Boolean.TRUE.equals(this.redisTemplate.hasKey(key));
  555. }
  556. /**
  557. * @param keyBytes key值
  558. * @return 是否存在
  559. * @Description: 是否存在当前key
  560. * @Author: chenzumao
  561. */
  562. private boolean hasKey(final byte[] keyBytes) {
  563. if (null == keyBytes || keyBytes.length == 0) {
  564. return false;
  565. }
  566. return Boolean.TRUE.equals(this.redisTemplate.execute(connection -> connection.exists(keyBytes), true));
  567. }
  568. public Long delKey(String key) {
  569. log.debug("cache del key:{}", key);
  570. byte[] bytes = serializeForString(key);
  571. if (!hasKey(bytes)) {
  572. log.info("没有找到指定的key【{}】", key);
  573. return 0L;
  574. }
  575. return this.redisTemplate.execute(connection ->
  576. connection.del(bytes), true);
  577. }
  578. }

五、测试类

  1. package com.vanchan.sca.common.domian;
  2. import lombok.Data;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.GenerationType;
  6. import javax.persistence.Id;
  7. import java.io.Serializable;
  8. //订单
  9. @Entity(name = "shop_order")
  10. @Data
  11. public class Order implements Serializable {
  12. /**
  13. * 订单id
  14. */
  15. @Id
  16. @GeneratedValue(strategy = GenerationType.IDENTITY)
  17. private Long oid;
  18. /**
  19. * 用户id
  20. */
  21. private Integer uid;
  22. /**
  23. *用户名
  24. */
  25. private String username;
  26. /**
  27. *商品id
  28. */
  29. private Integer pid;
  30. /**
  31. *商品名称
  32. */
  33. private String pname;
  34. /**
  35. *商品单价
  36. */
  37. private Double pprice;
  38. /**
  39. *购买数量
  40. */
  41. private Integer number;
  42. }
  1. package com.vanchan.sca.test.order;
  2. import com.alibaba.fastjson.JSON;
  3. import com.vanchan.sca.common.domian.Order;
  4. import com.vanchan.sca.order.OrderApplication;
  5. import com.vanchan.sca.order.service.CommonRedisCacheService;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.collections4.CollectionUtils;
  8. import org.junit.Test;
  9. import org.junit.runner.RunWith;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.boot.test.context.SpringBootTest;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  14. import java.util.*;
  15. /**
  16. * @author chenzumao
  17. * @Description TestRedisDemo
  18. * @since 2023/8/11 0:56
  19. */
  20. @RunWith(SpringJUnit4ClassRunner.class)
  21. @SpringBootTest(classes = {OrderApplication.class, TestRedisJsonDemo.class})
  22. @Slf4j
  23. public class TestRedisJsonDemo {
  24. @Autowired
  25. private CommonRedisCacheService commonRedisCacheService;
  26. @Autowired
  27. private RedisTemplate<String, Object> redisTemplate;
  28. public static final String ORDER_REDIS_KEY_MAP = "ORDER:OLD:KEY:MAP";
  29. public static final String ORDER_REDIS_OLD_KEY_MAP = "ORDER:OLD:KEY:MAP";
  30. public static final String ORDER_REDIS_NEW_KEY_MAP = "ORDER:NEW:KEY:MAP";
  31. public static final String ORDER_REDIS_NEW_KEY_STRING = "ORDER:KEY:STRING";
  32. public static final String ORDER_REDIS_LIST_DATA = "ORDER:LIST:KEY:DATA";
  33. public static final String ORDER_REDIS_SET_DATA = "ORDER:SET:KEY:DATA";
  34. /**
  35. * 原生redis存数据
  36. */
  37. @Test
  38. public void testPut() {
  39. Map<String, Object> orderMap = new HashMap<>();
  40. for (int i = 1; i < 4; i++) {
  41. Order order = new Order();
  42. order.setOid(Long.valueOf(i));
  43. order.setUid(i);
  44. order.setUsername("");
  45. order.setPid(i);
  46. order.setPname("");
  47. order.setPprice(0.0D);
  48. order.setNumber(0);
  49. orderMap.put(String.valueOf(i), order);
  50. }
  51. redisTemplate.opsForHash().putAll(ORDER_REDIS_OLD_KEY_MAP,orderMap);
  52. }
  53. /**
  54. * 批量推送HASH数据
  55. */
  56. @Test
  57. public void testPutAll() {
  58. Map<String, Object> orderMap = new HashMap<>();
  59. for (int i = 1; i < 4; i++) {
  60. Order order = new Order();
  61. order.setOid(Long.valueOf(i));
  62. order.setUid(i);
  63. order.setUsername("");
  64. order.setPid(i);
  65. order.setPname("");
  66. order.setPprice(0.0D);
  67. order.setNumber(0);
  68. orderMap.put(String.valueOf(i), order);
  69. }
  70. commonRedisCacheService.hPutAll(ORDER_REDIS_NEW_KEY_MAP, orderMap);
  71. Order order = new Order();
  72. order.setOid(Long.valueOf(7));
  73. order.setUid(7);
  74. order.setUsername("");
  75. order.setPid(7);
  76. order.setPname("");
  77. order.setPprice(0.0D);
  78. order.setNumber(0);
  79. commonRedisCacheService.hPut(ORDER_REDIS_NEW_KEY_MAP,"9", order);
  80. }
  81. /**
  82. * 查询hash数据
  83. */
  84. @Test
  85. public void testHashGetAll() {
  86. Map<String, Order> stringOrderMap = commonRedisCacheService.hGetAll(ORDER_REDIS_NEW_KEY_MAP, Order.class);
  87. if (stringOrderMap != null && !stringOrderMap.isEmpty()) {
  88. Iterator<Map.Entry<String, Order>> entryIterator = stringOrderMap.entrySet().iterator();
  89. while (entryIterator.hasNext()) {
  90. Map.Entry<String, Order> orderEntry = entryIterator.next();
  91. Order order = orderEntry.getValue();
  92. log.info("全量获取key【{}】当前值【{}】", orderEntry.getKey(), JSON.toJSONString(order));
  93. }
  94. } else {
  95. log.info("为空");
  96. }
  97. //hVals 命令获取hash 所有value值
  98. List<Order> list = commonRedisCacheService.hGetAllToList(ORDER_REDIS_NEW_KEY_MAP, Order.class);
  99. if(CollectionUtils.isNotEmpty(list)){
  100. log.info("hVals 命令获取hash 所有value值 获取到【{}】条,数据:{}",list.size(),JSON.toJSON(list));
  101. }else {
  102. log.info("hVals 命令获取hash 所有value值 为空");
  103. }
  104. Order order = commonRedisCacheService.hGet(ORDER_REDIS_NEW_KEY_MAP, "7", Order.class);
  105. log.info("单个查询接收到返回值:{}", (order != null ? JSON.toJSONString(order) : null));
  106. List<String> fields = new ArrayList<>();
  107. fields.add("3");
  108. fields.add("5");
  109. fields.add("9");
  110. List<Order> orderList = commonRedisCacheService.hGetAllToList(ORDER_REDIS_NEW_KEY_MAP, fields, Order.class);
  111. if(CollectionUtils.isNotEmpty(orderList)){
  112. log.info("指定field到【{}】条 值【{}】", orderList.size(), JSON.toJSONString(orderList));
  113. }
  114. }
  115. @Test
  116. public void testHGetOne() {
  117. }
  118. /**
  119. * 普通类型存取
  120. */
  121. @Test
  122. public void testPutAndGet() {
  123. for (int i = 1; i <= 2; i++) {
  124. Order order = new Order();
  125. order.setOid(Long.valueOf(i));
  126. order.setUid(i);
  127. order.setUsername("");
  128. order.setPid(9);
  129. order.setPname("");
  130. order.setPprice(0.0D);
  131. order.setNumber(0);
  132. String key = ORDER_REDIS_NEW_KEY_STRING + ":" + order.getUid();
  133. commonRedisCacheService.put(key, order);
  134. }
  135. log.info("插入成功");
  136. for (int i = 1; i <= 2; i++) {
  137. String key = ORDER_REDIS_NEW_KEY_STRING + ":" + i;
  138. Order o = commonRedisCacheService.get(key, Order.class);
  139. if (null != o) {
  140. log.info("key【{}】转化:{}", key, JSON.toJSONString(o));
  141. }
  142. }
  143. }
  144. /**
  145. * list类型存取
  146. */
  147. @Test
  148. public void testListPutAndGet() {
  149. for (int i = 1; i <= 2; i++) {
  150. Order order = new Order();
  151. order.setOid(Long.valueOf(i));
  152. order.setUid(i);
  153. order.setUsername("");
  154. order.setPid(9);
  155. order.setPname("");
  156. order.setPprice(0.0D);
  157. order.setNumber(0);
  158. //推送存储
  159. commonRedisCacheService.lRightPush(ORDER_REDIS_LIST_DATA,order);
  160. }
  161. log.info("插入成功");
  162. while (true){
  163. //左边开始读取
  164. try {
  165. Order order = commonRedisCacheService.listLeftPop(ORDER_REDIS_LIST_DATA, Order.class);
  166. if(null == order){
  167. break;
  168. }
  169. log.info("获取到:{}",JSON.toJSONString(order));
  170. } catch (Exception e) {
  171. log.error("异常信息:",e);
  172. }
  173. }
  174. }
  175. /**
  176. * set类型存取
  177. */
  178. @Test
  179. public void testSetPutAndGet() {
  180. for (int i = 1; i <= 2; i++) {
  181. Order order = new Order();
  182. order.setOid(Long.valueOf(i));
  183. order.setUid(i);
  184. order.setUsername("");
  185. order.setPid(9);
  186. order.setPname("");
  187. order.setPprice(0.0D);
  188. order.setNumber(0);
  189. //推送存储
  190. commonRedisCacheService.setAdd(ORDER_REDIS_SET_DATA,order);
  191. }
  192. log.info("插入成功");
  193. while (true){
  194. //左边开始读取
  195. try {
  196. Order order = commonRedisCacheService.setPop(ORDER_REDIS_SET_DATA, Order.class);
  197. if(null == order){
  198. break;
  199. }
  200. log.info("获取到:{}",JSON.toJSONString(order));
  201. } catch (Exception e) {
  202. log.error("异常信息:",e);
  203. }
  204. }
  205. }
  206. }

1.系列化后redis数据不带类信息:

2.调用测试方法获取数据

2.1 HASH类型:

根据key获取所有

根据key获取value集合

根据key和field集合获取value集合

2.2 String 类型

2.3 list类型

2.4 SET类型

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/590362
推荐阅读
相关标签
  

闽ICP备14008679号