1. Add dependencies and configuration
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
Add the following configuration in application.yaml:
spring: redis: # address host: localhost # port, default is 6379 port: 6379 # password password: # Connection timeout timeout: 10s lettuce: pool: # The minimum idle connection in the connection pool min-idle: 0 # The maximum idle connection in the connection pool max-idle: 8 # The maximum number of database connections in the connection pool max-active: 8 # #The maximum blocking waiting time of the connection pool (use a negative value to indicate no limit) max-wait: -1ms
2. Redis configuration class
(1) Redis configuration class to prevent the data stored in Redis from being binary or garbled
/** * redis configuration */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean @SuppressWarnings(value = { "unchecked", "rawtypes" }) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); serializer.setObjectMapper(mapper); template.setValueSerializer(serializer); // Use StringRedisSerializer to serialize and deserialize redis key values template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(serializer); template.setHashValueSerializer(serializer); template. afterPropertiesSet(); return template; } }
(2) Serialize using FastJson
/** * Redis uses FastJson serialization * */ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> { @SuppressWarnings("unused") private ObjectMapper objectMapper = new ObjectMapper(); public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private Class<T> clazz; static { ParserConfig.getGlobalInstance().setAutoTypeSupport(true); } public FastJson2JsonRedisSerializer(Class<T> clazz) { super(); this. clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes. length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return JSON. parseObject(str, clazz); } public void setObjectMapper(ObjectMapper objectMapper) { Assert.notNull(objectMapper, "'objectMapper' must not be null"); this.objectMapper = objectMapper; } protected JavaType getJavaType(Class<?> clazz) { return TypeFactory.defaultInstance().constructType(clazz); } }
2. Redis operation tool class
/** * spring redis tool class **/ @SuppressWarnings(value = { "unchecked", "rawtypes" }) @Component public class RedisCache { @Autowired public RedisTemplate redisTemplate; /** * Cache basic objects, Integer, String, entity classes, etc. * * @param key cache key value * @param value cached value * @return cached object */ public <T> ValueOperations<String, T> setCacheObject(String key, T value) { ValueOperations<String, T> operation = redisTemplate. opsForValue(); operation.set(key, value); return operation; } /** * Cache basic objects, Integer, String, entity classes, etc. * * @param key cache key value * @param value cached value * @param timeout time * @param timeUnit time granularity * @return cached object */ public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) { ValueOperations<String, T> operation = redisTemplate. opsForValue(); operation.set(key, value, timeout, timeUnit); return operation; } /** * Get the basic object of the cache. * * @param key cache key value * @return data corresponding to cache key */ public <T> T getCacheObject(String key) { ValueOperations<String, T> operation = redisTemplate. opsForValue(); return operation. get(key); } /** * Delete a single object * * @param key */ public void deleteObject(String key) { redisTemplate.delete(key); } /** * Delete collection object * * @param collection */ public void deleteObject(Collection collection) { redisTemplate.delete(collection); } /** * Cache List data * * @param key cache key value * @param dataList List data to be cached * @return cached object */ public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) { ListOperations listOperation = redisTemplate. opsForList(); if (null != dataList) { int size = dataList. size(); for (int i = 0; i < size; i ++ ) { listOperation. leftPush(key, dataList. get(i)); } } return listOperation; } /** * Get the cached list object * * @param key cache key value * @return data corresponding to cache key */ public <T> List<T> getCacheList(String key) { List<T> dataList = new ArrayList<T>(); ListOperations<String, T> listOperation = redisTemplate.opsForList(); Long size = listOperation. size(key); for (int i = 0; i < size; i ++ ) { dataList.add(listOperation.index(key, i)); } return dataList; } /** * Cache Set * * @param key cache key value * @param dataSet cached data * @return cached data object */ public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) { BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key); Iterator<T> it = dataSet. iterator(); while (it. hasNext()) { setOperation. add(it. next()); } return setOperation; } /** * Get cached set * * @param key * @return */ public <T> Set<T> getCacheSet(String key) { Set<T> dataSet = new HashSet<T>(); BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key); dataSet = operation. members(); return dataSet; } /** * Cache Map * * @param key * @param dataMap * @return */ public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) { HashOperations hashOperations = redisTemplate.opsForHash(); if (null != dataMap) { for (Map.Entry<String, T> entry : dataMap.entrySet()) { hashOperations. put(key, entry. getKey(), entry. getValue()); } } return hashOperations; } /** * Get the cached Map * * @param key * @return */ public <T> Map<String, T> getCacheMap(String key) { Map<String, T> map = redisTemplate.opsForHash().entries(key); return map; } /** * Get a list of cached basic objects * * @param pattern string prefix * @return object list */ public Collection<String> keys(String pattern) { return redisTemplate.keys(pattern); } }
3. Business class
@Service @Slf4j public class RedisLockServiceImpl implements RedisLockService { @Autowired private RedisCache redisCache; // commodity private static final String PRODUCT = "PRODUCT:PRODUCT_"; // in stock private static final String PRODUCT_STOCK = "PRODUCT:PRODUCT_STOCK_"; @Override public Result<String> saveProduct() { List<Product> products = new ArrayList<>(); products.add(Product.builder().id("N001").name("iPhone 12").build()); products.add(Product.builder().id("N002").name("iPhone 13").build()); products.add(Product.builder().id("N003").name("iPhone 14").build()); // add item data to cache for (Product product : products) { String productId = product. getId(); redisCache.setCacheObject(PRODUCT + productId, product); redisCache.setCacheObject(PRODUCT_STOCK + productId, 100); } return ResponseData.success("Added successfully"); } }
Note that the commodity entity class needs to be serialized:
The following figure shows the product information saved to Redis: