|
|
@@ -1,136 +1,170 @@
|
|
|
-package com.fs.framework.config;
|
|
|
+package com.fs.common.config;
|
|
|
|
|
|
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
|
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
|
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
-import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
|
|
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.connection.RedisConnectionFactory;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
|
import org.springframework.data.redis.serializer.GenericToStringSerializer;
|
|
|
-import org.springframework.data.redis.serializer.StringRedisSerializer;
|
|
|
+import org.springframework.data.redis.serializer.RedisSerializer;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
|
/**
|
|
|
- * redis配置
|
|
|
+ * Redis 配置类
|
|
|
*
|
|
|
-
|
|
|
+ * 说明:
|
|
|
+ * 1. 统一配置 RedisTemplate
|
|
|
+ * 2. Redis Key / HashKey 自动添加租户前缀(tenantid:xxx)
|
|
|
+ * 3. Value 使用 FastJson 序列化,支持复杂对象
|
|
|
+ * 4. 适用于多租户缓存场景,业务代码无需关心 Key 前缀
|
|
|
*/
|
|
|
@Configuration
|
|
|
-@EnableCaching
|
|
|
-public class RedisConfig extends CachingConfigurerSupport
|
|
|
-{
|
|
|
+public class RedisConfig extends CachingConfigurerSupport {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Redis Key 序列化器
|
|
|
+ * 统一在 Key 前添加租户前缀:tenantid:{tenantId}
|
|
|
+ */
|
|
|
@Bean
|
|
|
- @SuppressWarnings(value = { "unchecked", "rawtypes" })
|
|
|
- public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
|
|
|
- {
|
|
|
+ public RedisSerializer<String> tenantKeySerializer() {
|
|
|
+ return new TenantKeyRedisSerializer();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用 RedisTemplate(Object -> Object)
|
|
|
+ * 用于大多数业务缓存场景
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
|
+ public RedisTemplate<Object, Object> redisTemplate(
|
|
|
+ RedisConnectionFactory connectionFactory,
|
|
|
+ RedisSerializer<String> tenantKeySerializer) {
|
|
|
+
|
|
|
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
|
|
template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
|
|
|
+ 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.PROPERTY);
|
|
|
+ mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
|
|
serializer.setObjectMapper(mapper);
|
|
|
|
|
|
- // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
- template.setKeySerializer(new StringRedisSerializer());
|
|
|
- template.setValueSerializer(serializer);
|
|
|
+ // Key 使用租户前缀
|
|
|
+ template.setKeySerializer(tenantKeySerializer);
|
|
|
+ template.setHashKeySerializer(tenantKeySerializer);
|
|
|
|
|
|
- // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
- template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ // Value 使用 FastJson
|
|
|
+ template.setValueSerializer(serializer);
|
|
|
template.setHashValueSerializer(serializer);
|
|
|
|
|
|
template.afterPropertiesSet();
|
|
|
return template;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Boolean 类型 RedisTemplate
|
|
|
+ * 适用于状态标识、开关类缓存
|
|
|
+ */
|
|
|
@Bean
|
|
|
- public RedisTemplate<String, Boolean> redisTemplateForBoolean(RedisConnectionFactory connectionFactory) {
|
|
|
+ public RedisTemplate<String, Boolean> redisTemplateForBoolean(
|
|
|
+ RedisConnectionFactory connectionFactory,
|
|
|
+ RedisSerializer<String> tenantKeySerializer) {
|
|
|
+
|
|
|
RedisTemplate<String, Boolean> template = new RedisTemplate<>();
|
|
|
template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
- template.setKeySerializer(new StringRedisSerializer());
|
|
|
- template.setValueSerializer(new GenericToStringSerializer<>(Boolean.class));
|
|
|
+ template.setKeySerializer(tenantKeySerializer);
|
|
|
+ template.setHashKeySerializer(tenantKeySerializer);
|
|
|
|
|
|
- // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
- template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setValueSerializer(new GenericToStringSerializer<>(Boolean.class));
|
|
|
template.setHashValueSerializer(new GenericToStringSerializer<>(Boolean.class));
|
|
|
|
|
|
template.afterPropertiesSet();
|
|
|
return template;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Integer 类型 RedisTemplate
|
|
|
+ * 适用于计数、次数统计等场景
|
|
|
+ */
|
|
|
@Bean
|
|
|
- public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
|
|
|
+ public RedisTemplate<String, Integer> redisTemplateForInteger(
|
|
|
+ RedisConnectionFactory connectionFactory,
|
|
|
+ RedisSerializer<String> tenantKeySerializer) {
|
|
|
+
|
|
|
RedisTemplate<String, Integer> template = new RedisTemplate<>();
|
|
|
template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
- template.setKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setKeySerializer(tenantKeySerializer);
|
|
|
+ template.setHashKeySerializer(tenantKeySerializer);
|
|
|
|
|
|
- // 使用GenericToStringSerializer保证BigDecimal精度不丢失
|
|
|
template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
|
|
|
-
|
|
|
- // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
- template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
|
|
|
|
|
|
template.afterPropertiesSet();
|
|
|
return template;
|
|
|
}
|
|
|
- @Bean
|
|
|
- @SuppressWarnings(value = { "unchecked", "rawtypes" })
|
|
|
- public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {
|
|
|
- RedisTemplate<String, Object> template = new RedisTemplate<>();
|
|
|
- template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
|
|
|
+ /**
|
|
|
+ * BigDecimal 类型 RedisTemplate
|
|
|
+ * 适用于金额、精度要求较高的数据
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(
|
|
|
+ RedisConnectionFactory connectionFactory,
|
|
|
+ RedisSerializer<String> tenantKeySerializer) {
|
|
|
|
|
|
- ObjectMapper mapper = new ObjectMapper();
|
|
|
- mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
|
|
- mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
|
|
- serializer.setObjectMapper(mapper);
|
|
|
+ RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();
|
|
|
+ template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
- template.setKeySerializer(new StringRedisSerializer());
|
|
|
- template.setValueSerializer(serializer);
|
|
|
+ template.setKeySerializer(tenantKeySerializer);
|
|
|
+ template.setHashKeySerializer(tenantKeySerializer);
|
|
|
|
|
|
- // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
- template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
- template.setHashValueSerializer(serializer);
|
|
|
+ template.setValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
+ template.setHashValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
|
|
|
template.afterPropertiesSet();
|
|
|
return template;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * String Key + Object Value 的 RedisTemplate
|
|
|
+ * 常用于明确使用 String 作为 Key 的场景
|
|
|
+ */
|
|
|
@Bean
|
|
|
- public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
|
|
|
- RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();
|
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
|
+ public RedisTemplate<String, Object> redisTemplateForObject(
|
|
|
+ RedisConnectionFactory connectionFactory,
|
|
|
+ RedisSerializer<String> tenantKeySerializer) {
|
|
|
+
|
|
|
+ RedisTemplate<String, Object> template = new RedisTemplate<>();
|
|
|
template.setConnectionFactory(connectionFactory);
|
|
|
|
|
|
- // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
- template.setKeySerializer(new StringRedisSerializer());
|
|
|
+ FastJson2JsonRedisSerializer serializer =
|
|
|
+ new FastJson2JsonRedisSerializer(Object.class);
|
|
|
|
|
|
- // 使用GenericToStringSerializer保证BigDecimal精度不丢失
|
|
|
- template.setValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
+ ObjectMapper mapper = new ObjectMapper();
|
|
|
+ mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
|
|
+ mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
|
|
+ serializer.setObjectMapper(mapper);
|
|
|
|
|
|
- // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
- template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
- template.setHashValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
+ template.setKeySerializer(tenantKeySerializer);
|
|
|
+ template.setHashKeySerializer(tenantKeySerializer);
|
|
|
+
|
|
|
+ template.setValueSerializer(serializer);
|
|
|
+ template.setHashValueSerializer(serializer);
|
|
|
|
|
|
template.afterPropertiesSet();
|
|
|
return template;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
@Bean
|
|
|
public DefaultRedisScript<Long> limitScript()
|
|
|
{
|