使用方式:
//生成任务编码
String key = “applicationCode”+ LocalDate.now().format(DateTimeFormatter.ofPattern(“yyyyMMdd”));
String applicationCode = idTimeUtils.getDayIncrCode(“”,key,4);
import cn.hutool.core.util.StrUtil;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
/**
* @author
* @version 1.0
* @date 2021/10/9 16:17
*
* @desc 本工具类:用于生成(默认日期yyyyMMdd + 自定义位数)自增id
* 自增顺序有效期仅为当日,隔天清理
*/
@Service
public class IdTimeUtils {
@Autowired
RedisTemplate redisTemplate;
@Autowired
CacheService cacheService;
/**
* redis key的层级不能超过3层()
* 根据前缀+日期+每天的自增编号例如(WF2021041411200001)
*
* 使用方式 idTimeUtils.getDayIncrCode("SC", key, 5); 表示前缀SC,key 表示存在redis中的key, 5表示5位数
* 例如: 地区编号+日期+5为 可getDayIncrCode(010210,key随意建议直接存当天日期, 5)即可
*
* @param prefix 前缀,可以是地区编码组合 ,或任意字母
* @param key 表示存在redis中的key ,建议直接存当天日期加特殊符号前缀等
* @param length 表示自增位数位数
* @return 例如SC2021100900181 SC 20211009 00181
*/
public String getDayIncrCode(String prefix, String key, int length) {
String code = "";
String formatDay = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
Long dayEndTime = getAppointDateTimeMills();
//当天失效, 再加上300秒过期时间 防止凌晨系统时间不统一造成误差问题
long liveTime = (dayEndTime - System.currentTimeMillis()) / 1000 +300;
Long incre = getIncre(key, liveTime);
String sequence = getSequence(incre, length);
if (StrUtil.isNotBlank(prefix)) {
code = code + prefix;
}
code = code + formatDay + sequence;
return code;
}
public String getAttachmentName(String prefix, String key, int length) {
String code = "";
String formatDay = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
Long dayEndTime = getAppointDateTimeMills();
//当天失效, 再加上300秒过期时间 防止凌晨系统时间不统一造成误差问题
long liveTime = (dayEndTime - System.currentTimeMillis()) / 1000 +300;
Long incre = getIncre(key, liveTime);
String sequence = getSequence(incre, length);
code = code + formatDay +prefix+sequence;
return code;
}
/**
* 获取指定时间毫秒值
*
* @return
*/
public static Long getAppointDateTimeMills() {
Calendar ca = Calendar.getInstance();
//失效的时间
ca.set(Calendar.HOUR_OF_DAY, 23);
ca.set(Calendar.MINUTE, 59);
ca.set(Calendar.SECOND, 59);
long curtime = ca.getTimeInMillis();
return curtime;
}
/**
* 获取redis原子自增数据
*
* @param key
* @param liveTime
* @return
*/
public Long getIncre(String key, long liveTime) {
RedisAtomicLong counter = null;
RLock lock = cacheService.getRLock(key);
if (!redisTemplate.hasKey(key)) {
try {
lock.lock(5,TimeUnit.SECONDS);
counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
} finally {
lock.unlock();
}
} else {
counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
}
Long increment = counter.incrementAndGet();
//初始设置过期时间
boolean result = (null == increment || increment.longValue() == 0) && liveTime > 0;
if (result) {
counter.set(1);
counter.expire(liveTime, TimeUnit.SECONDS);
increment = 1L;
}
// 先增后拿,所以第一次为1时设置下过期时间
if (increment.longValue() == 1) counter.expire(liveTime, TimeUnit.SECONDS);
return increment;
}
/**
* 补全自增的数据
*
* @param seq
* @param length
* @return
*/
public static String getSequence(long seq, int length) {
String str = String.valueOf(seq);
int len = str.length();
// 取决于业务规模,应该不会到达4
if (len >= length) {
return str;
}
int rest = length - len;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rest; i++) {
sb.append('0');
}
sb.append(str);
return sb.toString();
}
}
CacheService
/**
* The type Redis service.
* 缓存服务
*/
@Component
public class CacheService implements InitializingBean, DisposableBean {
private static Logger logger = LoggerFactory.getLogger(CacheService.class);
// 缓存超时时间,单位:秒 ,默认1天
private int defaultExpireTime = 60 * 60 * 24;
@Resource
private RedisConfig redisConfig;
private RedissonClient redissonClient;
@Override
public void afterPropertiesSet() throws Exception {
redissonClient = redisConfig.createRedissonClient();
}
public void setWithSecondsTime(String key, int expireTime, Object value) {
this.getRBucket(redissonClient, key).set(value, expireTime, TimeUnit.SECONDS);
}
public void setAsync(String key, int expireTime, Object value) {
this.getRBucket(redissonClient, key).setAsync(value, expireTime, TimeUnit.SECONDS);
}
public void setForever(String key, Object value) {
this.getRBucket(redissonClient, key).set(value);
}
public void setWithSecondsTime(String key, Object value) {
this.getRBucket(redissonClient, key).set(value, defaultExpireTime, TimeUnit.SECONDS);
}
public void setExpireAtTime(String key, Object value, Date expireAtTime) {
RBucket<Object> rBucket = this.getRBucket(redissonClient, key);
rBucket.set(value);
rBucket.expireAt(expireAtTime);
}
public void setAsync(String key, Object value) {
this.getRBucket(redissonClient, key).setAsync(value, defaultExpireTime, TimeUnit.SECONDS);
}
public boolean isExists(String key) {
RKeys keys = redissonClient.getKeys();
long count = keys.countExists(key);
return count > 0;
}
public Object get(String key) {
return this.getRBucket(redissonClient, key).get();
}
public String getStringValue(String key) {
if (ObjectUtil.isNullObj(this.getRBucket(redissonClient, key).get())) {
return null;
}
return (String) this.getRBucket(redissonClient, key).get();
}
public void delete(String key) {
this.getRBucket(redissonClient, key).delete();
}
private <T> RBucket<T> getRBucket(RedissonClient redisson, String objectName) {
return redisson.getBucket(objectName);
}
public RLock getRLock(String objectName) {
return redissonClient.getLock(objectName);
}
public RAtomicLong getRAtomicLong(String objectName) {
return redissonClient.getAtomicLong(objectName);
}
public RScheduledExecutorService getScheduledTask(String key) {
return redissonClient.getExecutorService(key);
}
public void deletePrefix(String prefix) {
RKeys keys = redissonClient.getKeys();
keys.deleteByPattern(prefix + '*');
}
@Override
public void destroy() throws Exception {
redissonClient.shutdown();
logger.info("CacheService destroy redissonClient!");
}
public <K, V> RMap<K, V> getMap(String key) {
return redissonClient.getMap(key);
}
public <T> RList<T> getList(String key, Codec codec) {
return redissonClient.getList(key, codec);
}
public <T> RList<T> getList(String key) {
return redissonClient.getList(key);
}
public <T> RSortedSet<T> getSoredSet(String key) {
return redissonClient.getSortedSet(key);
}
public RBlockingQueue<Object> getRQueue(String key) {
return redissonClient.getBlockingQueue(key);
}
public void setExpireAtTime(String key, Object value, long expireTime, TimeUnit timeUnit) {
RBucket<Object> rBucket = this.getRBucket(redissonClient, key);
rBucket.set(value);
rBucket.expire(expireTime, timeUnit);
}
}