|
|
@@ -0,0 +1,161 @@
|
|
|
+package com.fs.framework.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 java.math.BigDecimal;
|
|
|
+
|
|
|
+/**
|
|
|
+ * redis配置
|
|
|
+ *
|
|
|
+
|
|
|
+ */
|
|
|
+@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.PROPERTY);
|
|
|
+ serializer.setObjectMapper(mapper);
|
|
|
+
|
|
|
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
+ template.setKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setValueSerializer(serializer);
|
|
|
+
|
|
|
+ // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
+ template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setHashValueSerializer(serializer);
|
|
|
+
|
|
|
+ template.afterPropertiesSet();
|
|
|
+ return template;
|
|
|
+ }
|
|
|
+ @Bean
|
|
|
+ public RedisTemplate<String, Boolean> redisTemplateForBoolean(RedisConnectionFactory connectionFactory) {
|
|
|
+ RedisTemplate<String, Boolean> template = new RedisTemplate<>();
|
|
|
+ template.setConnectionFactory(connectionFactory);
|
|
|
+
|
|
|
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
+ template.setKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setValueSerializer(new GenericToStringSerializer<>(Boolean.class));
|
|
|
+
|
|
|
+ // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
+ template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setHashValueSerializer(new GenericToStringSerializer<>(Boolean.class));
|
|
|
+
|
|
|
+ template.afterPropertiesSet();
|
|
|
+ return template;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
|
|
|
+ RedisTemplate<String, Integer> template = new RedisTemplate<>();
|
|
|
+ template.setConnectionFactory(connectionFactory);
|
|
|
+
|
|
|
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
+ template.setKeySerializer(new StringRedisSerializer());
|
|
|
+
|
|
|
+ // 使用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);
|
|
|
+
|
|
|
+ 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);
|
|
|
+
|
|
|
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
+ template.setKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setValueSerializer(serializer);
|
|
|
+
|
|
|
+ // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
+ template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setHashValueSerializer(serializer);
|
|
|
+
|
|
|
+ template.afterPropertiesSet();
|
|
|
+ return template;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
|
|
|
+ RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();
|
|
|
+ template.setConnectionFactory(connectionFactory);
|
|
|
+
|
|
|
+ // 使用StringRedisSerializer来序列化和反序列化redis的key值
|
|
|
+ template.setKeySerializer(new StringRedisSerializer());
|
|
|
+
|
|
|
+ // 使用GenericToStringSerializer保证BigDecimal精度不丢失
|
|
|
+ template.setValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
+
|
|
|
+ // Hash的key也采用StringRedisSerializer的序列化方式
|
|
|
+ template.setHashKeySerializer(new StringRedisSerializer());
|
|
|
+ template.setHashValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
|
|
|
+
|
|
|
+ template.afterPropertiesSet();
|
|
|
+ return template;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public DefaultRedisScript<Long> limitScript()
|
|
|
+ {
|
|
|
+ DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
|
|
|
+ redisScript.setScriptText(limitScriptText());
|
|
|
+ redisScript.setResultType(Long.class);
|
|
|
+ return redisScript;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 限流脚本
|
|
|
+ */
|
|
|
+ private String limitScriptText()
|
|
|
+ {
|
|
|
+ return "local key = KEYS[1]\n" +
|
|
|
+ "local count = tonumber(ARGV[1])\n" +
|
|
|
+ "local time = tonumber(ARGV[2])\n" +
|
|
|
+ "local current = redis.call('get', key);\n" +
|
|
|
+ "if current and tonumber(current) > count then\n" +
|
|
|
+ " return current;\n" +
|
|
|
+ "end\n" +
|
|
|
+ "current = redis.call('incr', key)\n" +
|
|
|
+ "if tonumber(current) == 1 then\n" +
|
|
|
+ " redis.call('expire', key, time)\n" +
|
|
|
+ "end\n" +
|
|
|
+ "return current;";
|
|
|
+ }
|
|
|
+}
|