1. 由于在项目中有很多地方需要用到自增序列,但是有时候直接用数据库的自增序列又不太方便,比如有些需求中要求有记录的编码,编码的规则就是字母加上自定义序列的组合,如:BM0001 类似的这种自增,那我们用的数据库MySQL做自增序列实现起来相比用Redis的自增要麻烦不少,有需要的朋友可自行了解,这里不做多介绍,这篇文章需要对Spring Boot和Redis有一定的了解,不了解的朋友看不懂可自行百度。废话不多说,先引入Redis依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. Redis序列化配置

    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.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.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
    
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            // key采用String的序列化方式
            template.setKeySerializer(stringRedisSerializer);
            // hash的key也采用String的序列化方式
            template.setHashKeySerializer(stringRedisSerializer);
            // value序列化方式采用jackson
            template.setValueSerializer(jackson2JsonRedisSerializer);
            // hash的value序列化方式采用jackson
            template.setHashValueSerializer(jackson2JsonRedisSerializer);
            template.afterPropertiesSet();
    
            return template;
        }
    }
    
  3. 写一个RedisUtil工具类

    @Slf4j
    @Component
    public class RedisUtil {
    
        @Resource
        private RedisTemplate<String, Object> redisTemplate;
    
        private RedisConnectionFactory connectionFactory;
        /**
         * 自增序列(有过期时间)
         * @param key 自增key
         * @param liveTime 存活时间(秒)
         * @return
         */
        public Long incr(String key, long liveTime) {
            if (null == connectionFactory) {
                connectionFactory = redisTemplate.getConnectionFactory();
            }
            assert connectionFactory != null;
            RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, connectionFactory);
            long increment = entityIdCounter.getAndIncrement();
            if (increment == 0 && liveTime > 0) {
                //初始设置过期时间
                entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
            }
            return increment;
        }
    
        /**
         * 自增序列(可设置初始值)
         * @param key 自增key
         * @param value 初始值
         * @description 若自增key已存在,并且初始值必须要大于生成的值,以免造成序列冲突
         * @return
         */
        public void setIncr(String key, int value) {
            if (value < 0) {
                value = 1;
            }
            if (null == connectionFactory) {
                connectionFactory = redisTemplate.getConnectionFactory();
            }
            assert connectionFactory != null;
            RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, connectionFactory);
            entityIdCounter.set(value);
        }
    
        public Long getIncr(String key) {
            if (null == connectionFactory) {
                connectionFactory = redisTemplate.getConnectionFactory();
            }
            assert connectionFactory != null;
            RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, connectionFactory);
            return entityIdCounter.getAndIncrement();
        }
    }
    
  4. 单元测试

    @Test
    public void testRedis() {
        long test_incr = redisUtil.getIncr("test_incr");
        if (test_incr < 100L) {
            redisUtil.setIncr("test_incr", 100);
            test_incr = redisUtil.getIncr("test_incr");
        }
        System.out.println(test_incr);
    }
    
  5. 结果:
    在这里插入图片描述

  6. 至此,Redis的自增序列实现完成,文章中有些地方参考了其他的大佬代码,若是有侵权,请留言,谢谢!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐