springboot+redis实现定制化的单据号或流水号
程序员文章站
2022-07-15 13:26:13
...
一、业务场景
公司各种业务都用到一个批次号、版本号、流水号等,这些号码都需要由一定的规律去生成,并且要实现自增的或者带特殊编号的功能。实现的方式有很多种,可以通过数据库表的自增来实现,也可以通过Redis的string类型的自增方法。现在就两种方式来对比一下。
二、springboot+Redis实现自增
1、导入Redis依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
2、编写service公共接口
/**
* 生成编号
* @author
*/
public interface NumberGenService {
/**
* 根据code生成编号
* 例:01
* @param code 前缀
* @return 编号
*/
String generateNumber(String code);
/**
* 根据code及年月生成编号
* 例子:20190501
* @param code 前缀
* @return 编号
*/
String generateNumberByMonth(String code);
/**
* 根据code及年月日生成编号
* 例子:2019050801
* @param code 前缀
* @return 编号
*/
String generateNumberByDay(String code);
/**
* 根据code及年月日生成编号
* 例子:2019050801
* @param code 前缀
* @param length 编号长度
* @return 编号
*/
String generateNumberByDay(String code, int length);
}
3、serviceImpl
import com.ehe.core.thread.LocalVariable;
import com.ehe.elder.service.NumberGenService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* 生成编号
* @author Sue
*/
@Service
public class NumberGenServiceImpl implements NumberGenService {
/** redis操作String */
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final int LENGTH = 2;
private static final DateTimeFormatter MONTH_FORMAT = DateTimeFormatter.ofPattern("yyyyMM");
private static final DateTimeFormatter DAY_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public String generateNumber (String code) {
return getNumber(code, "", LENGTH);
}
@Override
public String generateNumberByMonth (String code) {
return getNumber(code, MONTH_FORMAT.format(LocalDate.now()), LENGTH);
}
@Override
public String generateNumberByDay (String code) {
return getNumber(code, DAY_FORMAT.format(LocalDate.now()), LENGTH);
}
@Override
public String generateNumberByDay(String code, int length) {
return getNumber(code, DAY_FORMAT.format(LocalDate.now()), length);
}
private String getNumber(String code, String month, int length) {
// LocalVariable.getTenantCode() 租户编号,可以自己定义一个
String key = LocalVariable.getTenantCode() + ":" + code + ":" + month;
Long number = stringRedisTemplate.opsForValue().increment(key);
return month + StringUtils.leftPad(number != null ? number.toString() : "1", length, '0');
}
}
三、通过数据库自增实现
1、pojo
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @author 陳燃
*/
@Data
public class CreditAutoCode implements Serializable {
private Long id;
private Long year;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
private Byte delFlag;
private String remark;
private Long autoId;
}
2、工具
/**
* 获取编号:202012345
* @return
*/
private synchronized Long findCode(CurrentUser user) {
Long code = null;
//获取最大编号
CreditAutoCode autoCode = creditAutoCodeMapper.selectCode();
Long nowYear = Long.valueOf(
DateUtils.format(new Date(),DateUtils.DATE_PATTERN).substring(0,4).replaceAll("-",""));
CreditAutoCode creditAutoCode = new CreditAutoCode();
//最大年份为null,重新计算年份自增
if (autoCode == null || autoCode.getAutoId() == null){
code = Long.valueOf(getNewEquipmentNo(nowYear.toString(),null));
creditAutoCode.setYear(nowYear);
creditAutoCode.setCreateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setCreateTime(new Date());
creditAutoCode.setUpdateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setUpdateTime(new Date());
creditAutoCode.setAutoId(1L);
creditAutoCodeMapper.insert(creditAutoCode);
return code;
}
//年份不匹配,重新计算自增
if (!nowYear.equals(autoCode.getYear())){
code = Long.valueOf(getNewEquipmentNo(nowYear.toString(),null));
creditAutoCode.setYear(nowYear);
creditAutoCode.setCreateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setCreateTime(new Date());
creditAutoCode.setUpdateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setUpdateTime(new Date());
creditAutoCode.setAutoId(1L);
creditAutoCodeMapper.insert(creditAutoCode);
return code;
}
String newCode = getNewEquipmentNo(nowYear.toString(),autoCode.getAutoId().toString());
code = Long.valueOf(newCode);
creditAutoCode.setYear(nowYear);
creditAutoCode.setCreateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setCreateTime(new Date());
creditAutoCode.setUpdateBy(user == null ? CommonConstant.SYSTEM : user.getShowName());
creditAutoCode.setUpdateTime(new Date());
creditAutoCode.setAutoId(autoCode.getAutoId()+1);
creditAutoCodeMapper.insert(creditAutoCode);
return code;
}
/**
*
* @param equipmentType : 单据前缀,年份
* @param equipmentNo:自增编号
* @return
*/
public static String getNewEquipmentNo(String equipmentType, String equipmentNo){
String newEquipmentNo = equipmentType + "00001";
if(equipmentNo != null && !equipmentNo.isEmpty()){
int no = Integer.parseInt(equipmentNo);
int newEquipment = ++no;
newEquipmentNo = String.format(equipmentType + "%05d", newEquipment);
}
return newEquipmentNo;
}