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 操作接口实现
@Servicepublic class RedisDaoImpl implements RedisDao {@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic Boolean isExist(String key) {return redisTemplate.hasKey(key);}/*** 自增,+1,返回增长后的值** @param key* @return*/@Overridepublic long incr(String key) {return redisTemplate.opsForValue().increment(key);}/*** 设置过期时间** @param key*/@Overridepublic void expireKey(String key) {redisTemplate.expire(key, 36, TimeUnit.HOURS);}}
1.2 相关工具
1.2.1 补位工具
通过此工具来根据业务需要,填充流水号位数,未占用的位进行补“0”操作。
@Componentpublic 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 生成接口实现
@Servicepublic class SerialNumberServiceImpl implements SerialNumberService {@Autowiredprivate RedisDao redisDao;@Autowiredprivate ApplyCodeUtil applyCodeUtil;@Overridepublic 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()`方法即可生成对应的流水号。
