原理:
利用redis的RedisAtomicLong类实现该功能:
让其每天第一次放置一个新的自增的值(一天过期)
然后和每天的日期相加就可以了
例子: 20180901 + 001 ;当天就是 20180901 + 002
如果要多少个0,可以自己配置(工具类中)
一、pom.xml配置
<!-- redis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.2.RELEASE</version> </dependency>
二、redisTemplate配置
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; 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 { /** * retemplate相关配置 * @param factory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); // 配置连接工厂 template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSeial.setObjectMapper(om); // 值采用json序列化 template.setValueSerializer(jacksonSeial); //使用StringRedisSerializer来序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); // 设置hash key 和value序列化模式 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(jacksonSeial); template.afterPropertiesSet(); return template; } }
三、代码实现
import java.util.Set; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.support.atomic.RedisAtomicLong; import org.springframework.stereotype.Component; @Component public class CacheService { //这里因为有其他的template,所以名字起得不好看 @Autowired RedisTemplate<String, Object> ObjectRedisTemplate; public Long getIncrementNum(String key) { // 不存在准备创建 键值对 RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); Long counter = entityIdCounter.incrementAndGet(); if ((null == counter || counter.longValue() == 1)) {// 初始设置过期时间 System.out.println("设置过期时间为1天!"); entityIdCounter.expire(1, TimeUnit.DAYS);// 单位天 } return counter; } }
四、工具类(可以直接添加方法)
public class SequenceUtils { static final int DEFAULT_LENGTH = 3; public static String getSequence(long seq) { String str = String.valueOf(seq); int len = str.length(); if (len >= DEFAULT_LENGTH) {// 取决于业务规模,应该不会到达3 return str; } int rest = DEFAULT_LENGTH - len; StringBuilder sb = new StringBuilder(); for (int i = 0; i < rest; i++) { sb.append('0'); } sb.append(str); return sb.toString(); } }
五、测试
String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date()); Long num = cacheService.getIncrementNum("demo_get_the_new_" + "test3_"+currentDate); String flowCode = SequenceUtils.getSequence(num); logger.info("流水号: " + flowCode);
六、控制台输出
设置过期时间为1天! 流水号0001 设置过期时间为1天! 流水号0002
一个95后程序员的自述:
现在的我还年轻,还有激情,要在有限的时间和激情里实现自我价值.