前言
涉及的相关知识推荐阅读:
此文主要以Demo为例,对此直奔主题
以下Demo有参考价值
Demo
接口文件:
/**
* 使用redis生成分布式ID
*/
public interface IdGeneratorService {
/**
* @param biz 业务名称
*/
long generatorId(String biz);
/**
*
* @return
*/
long generatorId();
/**
* 返回工单号 customizerStr-日期-序号
* @param customizerStr 自定义参数
*/
String generatorOrderNo(String customizerStr);
}
其生成的工单函数如下:
import com.google.common.base.Strings;
import org.springblade.equipment.service.IdGeneratorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class RedisIdGeneratorService implements IdGeneratorService {
private static final String keyPrefix = "smart";
/**
* JedisClient对象
*/
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* @Description
* @author butterfly
*/
private String getIDPrefix() {
Date date = new Date();
Calendar c = Calendar.getInstance();
c.setTime(date);
int year = c.get(Calendar.YEAR);
int day = c.get(Calendar.DAY_OF_YEAR); // 今天是第多少天
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
String dayFmt = String.format("%1$03d", day); // 0补位操作 必须满足三位
String hourFmt = String.format("%1$02d", hour); // 0补位操作 必须满足2位
String minuteFmt = String.format("%1$02d", minute); // 0补位操作 必须满足2位
String secondFmt = String.format("%1$02d", second); // 0补位操作 必须满足2位
StringBuffer prefix = new StringBuffer();
prefix.append((year - 2000)).append(dayFmt).append(hourFmt).append(minuteFmt).append(secondFmt);
return prefix.toString();
}
/**
* 自定义工单前缀
*/
private String getOrderNoPrefix(String customizerStr){
StringBuffer prefix = new StringBuffer();
LocalDate now = LocalDate.now();
prefix.append(customizerStr).append("-").append(now.getYear()).append(now.getMonthValue()).append(now.getDayOfMonth());
return prefix.toString();
}
/**
* @author butterfly
*/
private long incrDistrId(String biz) {
String prefix = getIDPrefix();
String orderId = null;
String key = "#{biz}:id:".replace("#{biz}", biz).concat(prefix); // 00001
try {
ValueOperations<String, Object> valueOper = redisTemplate.opsForValue();
Long index = valueOper.increment(key, 1);
orderId = prefix.concat(String.format("%1$05d", index)); // 补位操作 保证满足5位
} catch (Exception ex) {
log.error("分布式订单号生成失败异常。。。。。", ex);
} finally {
redisTemplate.expire(key, 600, TimeUnit.SECONDS);//保留10分钟内的key
}
if (Strings.isNullOrEmpty(orderId)) return 0;
return Long.parseLong(orderId);
}
/**
* @Description 生成分布式ID
* @author butterfly
*/
@Override
public long generatorId(String biz) {
// 转成数字类型,可排序
return incrDistrId(biz);
}
@Override
public long generatorId() {
return incrDistrId(keyPrefix);
}
/**
* 获得前缀
* 去redis查看是否有对应的值
* 有的话取回来新增 001-》002
* 没有的直接插入,值为001
* 设置过期时间24小时
* @param customizerStr 自定义参数
* @return
*/
@Override
public String generatorOrderNo(String customizerStr) {
String orderNoPrefix = this.getOrderNoPrefix(customizerStr);
String key = orderNoPrefix;
String value ="";
try{
ValueOperations<String, Object> valueOper = redisTemplate.opsForValue();
Object o = valueOper.get(key);
//没有的直接插入,值为001
if(o==null){
valueOper.set(key,1);
value="001";
}else{
//有的话取回来新增 001-》002
Integer oldValue = Integer.valueOf(o.toString());
int newValue = oldValue + 1;
valueOper.set(key,newValue);
//其中0表示补零而不是补空格,6表示至少6位
value=String.format("%03d",newValue);
}
}catch (Exception e){
log.error("工单no生成失败,reason:"+e);
}finally {
redisTemplate.expire(key,24,TimeUnit.HOURS);
}
return key+"-"+value;
}
}