1. 基于Redis实现的发号机
使用RedisTemplate操作Redis,基于Redis的integer
类型,使用自增方法来获取对应的流水号。
1.1 Redis相关操作封装
1.1.1 操作接口
public interface RedisDao {
/**
* 指定key是否存在
*
* @param key
* @return
*/
Boolean isExist(String key);
/**
* 自增,+1,返回增长后的值
*
* @param key
* @return
*/
long incr(String key);
/**
* 配置过期时间
*
* @param key
*/
void expireKey(String key);
}
1.1.2 操作接口实现
@Service
public class RedisDaoImpl implements RedisDao {
@Autowired
private RedisTemplate redisTemplate;
@Override
public Boolean isExist(String key) {
return redisTemplate.hasKey(key);
}
/**
* 自增,+1,返回增长后的值
*
* @param key
* @return
*/
@Override
public long incr(String key) {
return redisTemplate.opsForValue().increment(key);
}
/**
* 设置过期时间
*
* @param key
*/
@Override
public void expireKey(String key) {
redisTemplate.expire(key, 36, TimeUnit.HOURS);
}
}
1.2 相关工具
1.2.1 补位工具
通过此工具来根据业务需要,填充流水号位数,未占用的位进行补“0”操作。
@Component
public class ApplyCodeUtil {
public ApplyCodeUtil() {
}
@Value("${applyCode.length}")
int DEFAULT_LENGTH;
/**
* 获得 DEFAULT_LENGTH 位的序列号,长度不足 DEFAULT_LENGTH 位,前面补0
*
* @param seq
* @return
*/
public 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();
}
}
可以通过在配置文件中对applyCode.length
进行配置,来决定流水号占位长度。
1.2.2 日期处理工具
import cn.hutool.core.date.DateUtil;
public class TimeUtil {
/**
* 获取今日日期
*
* @return
*/
public static String getToday() {
return DateUtil.format(DateUtil.date(), "yyyyMMdd");
}
}
1.3 流水号生成
1.3.1 生成接口
public interface SerialNumberService {
/**
* redis中的业务前缀key
*/
String SERIAL_NUMBER = "bussiness:applyCode:";
/**
* 根据两位业务码字符串,生成一个流水号,格式按照:<br/>
* yyyyMMdd{自增序列号}
* 两位,00-99
* @return 序列号
* @throws LJBaseException
*/
String generate() throws LJBaseException;
}
1.3.2 生成接口实现
@Service
public class SerialNumberServiceImpl implements SerialNumberService {
@Autowired
private RedisDao redisDao;
@Autowired
private ApplyCodeUtil applyCodeUtil;
@Override
public String generate() throws LJBaseException {
/** 获取今天的日期:yyyyMMdd */
String date = TimeUtil.getToday();
/** 构造redis的key */
String key = SERIAL_NUMBER + date;
/** 自增 */
Boolean exist = redisDao.isExist(key);
long sequence = redisDao.incr(key);
if (exist == null || !exist) {
redisDao.expireKey(key);
}
String seq = applyCodeUtil.getSequence(sequence);
StringBuilder sb = new StringBuilder();
sb.append(date).append(seq);
String serial = sb.toString();
return serial;
}
}
<br />至此,我们的简单流水号生成器就完成了,调用`SerialNumberService`中的`generate()`方法即可生成对应的流水号。