Poser une question
Comment utiliser jAVA pour générer des numéros de série tout en prenant en charge la configurabilité et une simultanéité élevée ???
Résoudre le problème
Supposons que votre projet ait intégré technologie de mise en cache
Si vous disposez d'une certaine base Java
Si...
Le code suivant implémente un générateur de numéros de série qui prend en charge une concurrence élevée, est configurable et hautement efficace. Pour une utilisation simultanée par plusieurs modules d'un projet, les numéros de série prennent en charge la mise en cache, c'est-à-dire qu'un certain nombre de numéros de série seront pré-générés et stockés dans le cache à chaque fois que nécessaire. le cache en premier. Une fois les numéros de série dans le cache utilisés, régénérez un certain nombre de numéros de série et mettez-les dans le cache. Répétez ce cycle pour améliorer l'efficacité...
En même temps, le numéro de série. Le générateur de nombres est thread-safe et protégé par des verrous de thread. Il a été véritablement investi dans le projet.
Conception de table de base de données
[code]CREATE TABLE sys_serial_number2 ( "id" varchar(32) COLLATE "default" NOT NULL, "module_name" varchar(50) COLLATE "default", "module_code" varchar(50) COLLATE "default", "config_templet" varchar(50) COLLATE "default", "max_serial" varchar(32) COLLATE "default", "pre_max_num" varchar(32) COLLATE "default", "is_auto_increment" char(1) COLLATE "default" )
Instructions :
<🎜. >[code]module_name:模块名称 module_code:模块编码 config_templet:当前模块 使用的序列号模板 max_serial:存放当前序列号的值 pre_max_num:预生成序列号存放到缓存的个数 is_auto_increment:是否自动增长模式,0:否 1:是
is_auto_increment est configuré sur 1. À l'heure actuelle, le numéro de série généré par le modèle de configuration pour CX000000 est : CX1, CX2, CX3…..
la configuration est 0, puis les numéros de série générés par le modèle de configuration pour CX0000000 sont : CX00000001, CX00000002 , CX00000003
Instructions de configuration de la base de données : Si vous avez besoin du numéro de projet du module de projet, vous devez configurer un enregistrement dans la table de la base de données sys_serial_number :
[code]| id | module_name | module_code | config_templet | max_serial | pre_max_num | is_auto_increment |-------|--------------|--------------|-----------------|-------------|-------------|--------------------/ | xxxx | 项目 | PJ |CX00000000${DATE}| 2650 | 100 | 1
Conception de l'entité du modèle de numéro de série :
[code]package com.evada.de.serialnum.model; import com.evada.de.common.model.BaseModel; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * 功能描述:序列号表模型 * * @author :Ay 2015/11/23 */ @Entity @Table(name="sys_serial_number") public class SystemSerialNumber extends BaseModel { /** * 模块名称 */ @Column(name = "module_name", columnDefinition = "VARCHAR") private String moduleName; /** * 模块编码 */ @Column(name = "module_code", columnDefinition = "VARCHAR") private String moduleCode; /** * 流水号配置模板 */ @Column(name = "config_templet", columnDefinition = "VARCHAR") private String configTemplet; /** * 序列号最大值 */ @Column(name = "max_serial", columnDefinition = "VARCHAR") private String maxSerial; /** * 是否自动增长标示 */ @Column(name = "is_auto_increment", columnDefinition = "VARCHAR") private String isAutoIncrement; public String getIsAutoIncrement() { return isAutoIncrement; } public void setIsAutoIncrement(String isAutoIncrement) { this.isAutoIncrement = isAutoIncrement; } /** * 预生成流水号数量 */ @Column(name = "pre_max_num", columnDefinition = "VARCHAR") private String preMaxNum; public String getPreMaxNum() { return preMaxNum; } public void setPreMaxNum(String preMaxNum) { this.preMaxNum = preMaxNum; } public String getModuleName() { return moduleName; } public void setModuleName(String moduleName) { this.moduleName = moduleName; } public String getModuleCode() { return moduleCode; } public void setModuleCode(String moduleCode) { this.moduleCode = moduleCode; } public String getConfigTemplet() { return configTemplet; } public void setConfigTemplet(String configTemplet) { this.configTemplet = configTemplet; } public String getMaxSerial() { return maxSerial; } public void setMaxSerial(String maxSerial) { this.maxSerial = maxSerial; } public SystemSerialNumber(String id){ this.id = id; } public SystemSerialNumber(String id,String moduleCode){ this.id = id; this.moduleCode = moduleCode; } public SystemSerialNumber(){} }
[code]package com.evada.de.serialnum.service; import com.evada.de.serialnum.dto.SystemSerialNumberDTO; /** * 序列号service接口 * Created by huangwy on 2015/11/24. */ public interface ISerialNumService { public SystemSerialNumberDTO find(SystemSerialNumberDTO systemSerialNumberDTO); public String generateSerialNumberByModelCode(String moduleCode); /** * 设置最小值 * @param value 最小值,要求:大于等于零 * @return 流水号生成器实例 */ ISerialNumService setMin(int value); /** * 设置最大值 * @param value 最大值,要求:小于等于Long.MAX_VALUE ( 9223372036854775807 ) * @return 流水号生成器实例 */ ISerialNumService setMax(long value); /** * 设置预生成流水号数量 * @param count 预生成数量 * @return 流水号生成器实例 */ ISerialNumService setPrepare(int count); }
[code]package com.evada.de.serialnum.service.impl; import com.evada.de.common.constants.SerialNumConstants; import com.evada.de.serialnum.dto.SystemSerialNumberDTO; import com.evada.de.serialnum.model.SystemSerialNumber; import com.evada.de.serialnum.repository.SerialNumberRepository; import com.evada.de.serialnum.repository.mybatis.SerialNumberDAO; import com.evada.de.serialnum.service.ISerialNumService; import com.evada.inno.common.util.BeanUtils; import com.evada.inno.common.util.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachePut; import org.springframework.stereotype.Service; import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.locks.ReentrantLock; /** * Created by Ay on 2015/11/24. */ @Service("serialNumberService") public class SerialNumberServiceImpl implements ISerialNumService { private static final Logger LOGGER = LoggerFactory.getLogger(SerialNumberServiceImpl.class); @Autowired private SerialNumberDAO serialNumberDAO; @Autowired private SerialNumberRepository serialNumberRepository; /** 格式 */ private String pattern = ""; /** 生成器锁 */ private final ReentrantLock lock = new ReentrantLock(); /** 流水号格式化器 */ private DecimalFormat format = null; /** 预生成锁 */ private final ReentrantLock prepareLock = new ReentrantLock(); /** 最小值 */ private int min = 0; /** 最大值 */ private long max = 0; /** 已生成流水号(种子) */ private long seed = min; /** 预生成数量 */ private int prepare = 0; /** 数据库存储的当前最大序列号 **/ long maxSerialInt = 0; /** 当前序列号是否为个位数自增的模式 **/ private String isAutoIncrement = "0"; SystemSerialNumberDTO systemSerialNumberDTO = new SystemSerialNumberDTO(); /** 预生成流水号 */ HashMap<String,List<String>> prepareSerialNumberMap = new HashMap<>(); /** * 查询单条序列号配置信息 * @param systemSerialNumberDTO * @return */ @Override public SystemSerialNumberDTO find(SystemSerialNumberDTO systemSerialNumberDTO) { return serialNumberDAO.find(systemSerialNumberDTO); } /** * 根据模块code生成预数量的序列号存放到Map中 * @param moduleCode 模块code * @return */ @CachePut(value = "serialNumber",key="#moduleCode") public List<String> generatePrepareSerialNumbers(String moduleCode){ //临时List变量 List<String> resultList = new ArrayList<String>(prepare); lock.lock(); try{ for(int i=0;i<prepare;i++){ maxSerialInt = maxSerialInt + 1; if(maxSerialInt > min && (maxSerialInt + "").length() < max ){ seed = maxSerialInt ; }else{ //如果动态数字长度大于模板中的长度 例:模板CF000 maxSerialInt 1000 seed = maxSerialInt = 0; //更新数据,重置maxSerialInt为0 systemSerialNumberDTO.setMaxSerial("0"); SystemSerialNumber systemSerialNumber = new SystemSerialNumber(); BeanUtils.copyProperties(systemSerialNumber,systemSerialNumberDTO); serialNumberRepository.save(systemSerialNumber); } //动态数字生成 String formatSerialNum = format.format(seed); //动态日期的生成 if(pattern.contains(SerialNumConstants.DATE_SYMBOL)){ String currentDate = DateUtils.format(new Date(),"yyyyMMdd"); formatSerialNum = formatSerialNum.replace(SerialNumConstants.DATE_SYMBOL,currentDate); } resultList.add(formatSerialNum); } //更新数据 systemSerialNumberDTO.setMaxSerial(maxSerialInt + ""); SystemSerialNumber systemSerialNumber = new SystemSerialNumber(); BeanUtils.copyProperties(systemSerialNumber,systemSerialNumberDTO); serialNumberRepository.save(systemSerialNumber); }finally{ lock.unlock(); } return resultList; } /** * 根据模块code生成序列号 * @param moduleCode 模块code * @return 序列号 */ public String generateSerialNumberByModelCode(String moduleCode){ //预序列号加锁 prepareLock.lock(); try{ //判断内存中是否还有序列号 if(null != prepareSerialNumberMap.get(moduleCode) && prepareSerialNumberMap.get(moduleCode).size() > 0){ //若有,返回第一个,并删除 return prepareSerialNumberMap.get(moduleCode).remove(0); } }finally { //预序列号解锁 prepareLock.unlock(); } systemSerialNumberDTO = new SystemSerialNumberDTO(); systemSerialNumberDTO.setModuleCode(moduleCode); systemSerialNumberDTO = serialNumberDAO.find(systemSerialNumberDTO); prepare = Integer.parseInt(systemSerialNumberDTO.getPreMaxNum().trim());//预生成流水号数量 pattern = systemSerialNumberDTO.getConfigTemplet().trim();//配置模板 String maxSerial = systemSerialNumberDTO.getMaxSerial().trim(); //存储当前最大值 isAutoIncrement = systemSerialNumberDTO.getIsAutoIncrement().trim(); maxSerialInt = Long.parseLong(maxSerial.trim());//数据库存储的最大序列号 max = this.counter(pattern,'0') + 1;//根据模板判断当前序列号数字的最大值 if(isAutoIncrement.equals("1")){ pattern = pattern.replace("0","#"); } format = new DecimalFormat(pattern); //生成预序列号,存到缓存中 List<String> resultList = generatePrepareSerialNumbers(moduleCode); prepareLock.lock(); try { prepareSerialNumberMap.put(moduleCode, resultList); return prepareSerialNumberMap.get(moduleCode).remove(0); } finally { prepareLock.unlock(); } } /** * 设置最小值 * * @param value 最小值,要求:大于等于零 * @return 流水号生成器实例 */ public ISerialNumService setMin(int value) { lock.lock(); try { this.min = value; }finally { lock.unlock(); } return this; } /** * 最大值 * * @param value 最大值,要求:小于等于Long.MAX_VALUE ( 9223372036854775807 ) * @return 流水号生成器实例 */ public ISerialNumService setMax(long value) { lock.lock(); try { this.max = value; }finally { lock.unlock(); } return this; } /** * 设置预生成流水号数量 * @param count 预生成数量 * @return 流水号生成器实例 */ public ISerialNumService setPrepare(int count) { lock.lock(); try { this.prepare = count; }finally { lock.unlock(); } return this; } /** * 统计某一个字符出现的次数 * @param str 查找的字符 * @param c * @return */ private int counter(String str,char c){ int count=0; for(int i = 0;i < str.length();i++){ if(str.charAt(i)==c){ count++; } } return count; } }