- 浏览: 8196 次
- 性别:
- 来自: 上海
文章分类
最新评论
需求说明:
解决办法:
一、分析需求,可确认销售订单序号的规则为“XS-日期-序号”,其中“序号”要以“日期”为因子进行归零递归。抽象出生成序号的规则“XS-{DATE}-{S4[DATE]}”。
其他可能应用到规则如下:
二、创建相关数据库表,规则定义表RuleDef,规则实例表RuleInst。定义表与实例表为一对多关系。
规则定义表RuleDef
规则实例表RuleInst
三、编写实现类(以正则表达式方式实现)
1、正则表达式properties配置设置
2、现实类SequenceUtils.java
3、测试类
- 进销存销售产品时,需要系统按规则生成一个销售订单号
- 订单号需要生成如"XS-日期-序号"的格式。其中“日期”为当天日期、“序号”为当天当前的销售单量并且不足四位时,以“0”填充在数量之前。如“XS-20100501-0050”
- 可以系统中维护订单号生成规则,并且不影响之前生成的订单号
解决办法:
一、分析需求,可确认销售订单序号的规则为“XS-日期-序号”,其中“序号”要以“日期”为因子进行归零递归。抽象出生成序号的规则“XS-{DATE}-{S4[DATE]}”。
其他可能应用到规则如下:
1. {Y} | {Y4} | {YYYY} / {Y2} | {YY} 表示获取年份值,四位数年份及二位数年份 2. {MM} | {M} 表示月份值 3. {DD} | {D}表示当前日期值 4. {HH} 表示日期时间的小时值 5. {MN} 表示日期时间的分钟值 6. {SS} 表示日期时间的秒值 7. {DATE} 表示当前日期同等于{YYYY}{MM}{DD}相连 8. {NOW} 表示当前日期时间{YYYY}{MM}{DD}{HH}{MN}{SS} 9. {@表单字段} 表示获取表单上某一控件的值为规则的一部分,如{@ORG}:获取表单上字段叫为"ORG"控件的值为规则一部分 10. {@表单字段:replace(a,b)}/{@表单字段:replace(a)} 表示获取表单上某一控件的值,并替换值中的"a"为"b"字符,如{@createTime:replace(-)}:获取表单上字段叫为"createTime"控件的值并替换"-"为空字符。注意(支持函数):替换[replace(a,b)],截取字符[substring(开始位置,结束位置)],转小写(toLowerCase),转大写(toUpperCase),去除前后空格(trim) 11.{W#*} 表示随机字符或数字,*号为长度,#为"D"时为随机数字(0-9);为"S"时为随机字符(A-Za-z);为空时为(0-9A-Za-z) 12.{D*} 表示随机*位数字,*号为长度,如{D5}为随机5位数字,等同与{WD5} 13.{C*} 表示随机*位字符,*号为长度,如{S5}为随机5位数字,等同与{WS5} 14.{S*[#_#]}表示序号中流水号长度及增长因子(必须以S开始),其中*表示序号中流水号长度;[]之间的设置为增长因子设置,可使用上面(1-9项)的任意一种及组合,如多个组合需要使用"_"相隔。如:S5[Y_M_D]表示序号中的流水号长度为5,并且每天都会自动归1,然后重新递增
二、创建相关数据库表,规则定义表RuleDef,规则实例表RuleInst。定义表与实例表为一对多关系。
规则定义表RuleDef
字段描述 | 字段名称 | 字段类型 |
id | definitionId | bigint |
规则序号名称 | definitionName | varchar(50) |
规则序号描述 | definitionComment | varchar(50) |
规则序号定义 | definitionRule | varchar(100) |
规则实例表RuleInst
字段描述 | 字段名称 | 字段类型 |
id | definitionId | bigint |
规则序号名称 | definitionName | varchar(50) |
序号增长因子 | iterateGene | varchar(50) |
当前最大值 | maxValue | int |
三、编写实现类(以正则表达式方式实现)
1、正则表达式properties配置设置
################################################## # custom Sequence pattern -- use SequenceRender ################################################## sequence.utils.growthFactorPattern=\\{S{1}(\\d){1,2}(?\:\\[([\\w\\@]*)\\])*\\} sequence.utils.commonRulePattern=\\{([\\w-\\@\\[\\]]+)(?\:\\\:([^\\{]*))*\\} sequence.utils.commonRuleFnPattern=([\\w-\\[\\]]*)(?\:\\((.*?)?\\))* sequence.utils.randomPattern=^W?(W|D|C){1}(\\d){1,2} #值为yyyyMMddHHmmss格式的当前日期时间值 sequence.utils.oraDatePattern=(((\\d{2}(\\d{2}))(\\d{2}))(\\d{2}))(\\d{2})(\\d{2})(\\d{2}) ################################################## # custom Sequence date Rule values -- use SequenceRender # 以下键值为sequence.utils.oraDatePattern正则值的索引号 ################################################## #yyyyMMddHHmmss=20110630115830 sequence.utils.YYYYMMDDHHMMSS=0 sequence.utils.NOW=${sequence.utils.YYYYMMDDHHMMSS} sequence.utils.YYYYMMDD=1 sequence.utils.DATE=${sequence.utils.YYYYMMDD} sequence.utils.YYYYMM=2 sequence.utils.YYYY=3 sequence.utils.Y4=${sequence.utils.YYYY} sequence.utils.Y=${sequence.utils.YYYY} sequence.utils.YY=4 sequence.utils.Y2=${sequence.utils.YY} sequence.utils.MM=5 sequence.utils.M=${sequence.utils.MM} sequence.utils.DD=6 sequence.utils.D=${sequence.utils.DD} sequence.utils.HH=7 sequence.utils.MN=8 sequence.utils.SS=9 sequence.define.xiaoShouNo=XS-{DATE}-{S4[DATE]}
2、现实类SequenceUtils.java
package test.inkcar.sequence.utils; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.beanutils.BeanUtils; import test.inkcar.sequence.preferences.SystemGlobal; public class SequenceUtils { // private static PtSequenceDefinitionBIZ ptSequenceDefinitionBIZ = // (PtSequenceDefinitionBIZ) BizFactory // .getBean("ptsequencedefinitionbiz"); // private static PtSequenceInstanceBIZ ptSequenceInstanceBIZ = // (PtSequenceInstanceBIZ) BizFactory // .getBean("ptsequenceinstancebiz"); /** * 配置属性前缀名称 */ private static final String PROPERTY_NAME = "sequence.utils."; /** * 带时分秒的ORA标准时间格式 yyyyMMddHHmmss */ private static final SimpleDateFormat ORA_DATE_TIME_EXTENDED_FORMAT = new SimpleDateFormat( "yyyyMMddHHmmss"); /** * 带时分秒的ORA标准时间正则解析表达式 */ private static final Pattern ORA_DATE_PATTERN = Pattern.compile( getPropertyName("oraDatePattern"), Pattern.CASE_INSENSITIVE); /** * 增长因子正则解析表达式 */ private static final Pattern GROWTH_FACTOR_PATTERN = Pattern.compile( getPropertyName("growthFactorPattern"), Pattern.CASE_INSENSITIVE); /** * 随机字符正则解析表达式 */ private static final Pattern RANDOM_PATTERN = Pattern.compile( getPropertyName("randomPattern"), Pattern.CASE_INSENSITIVE); /** * 规则正则解析表达式 -- 表单值 */ private static final Pattern COMMON_RULE_PATTERN = Pattern.compile( getPropertyName("commonRulePattern"), Pattern.CASE_INSENSITIVE); /** * 规则正则解析表达式--表单值函数 */ private static final Pattern COMMON_RULE_FN_PATTERN = Pattern.compile( getPropertyName("commonRuleFnPattern"), Pattern.CASE_INSENSITIVE); /** * 带时分秒的ORA标准时间格式匹配 */ private static Matcher ORA_DATE_MATCHER; /** * 客户请求数据 */ @SuppressWarnings("unchecked") private static ThreadLocal<Map> USERDATA = new ThreadLocal<Map>(); /** * 构造 */ private SequenceUtils() { } /** * 获取配置属性 * * @param name * 属性名称 * @return 配置值 */ private static final String getPropertyName(String name) { return SystemGlobal.get(PROPERTY_NAME + name); } /** * 初始化当前日期时间字符串及客户端请求数据 */ @SuppressWarnings("unchecked") private static final void reloadData(Object bean) { Map map = new HashMap(); if (bean != null) { if ("HashMap".equals(bean.getClass().getSimpleName())) { map = (Map) bean; } else { try { map = BeanUtils.describe(bean); } catch (Exception e) { e.printStackTrace(); } } } USERDATA.set(map); String dte = ORA_DATE_TIME_EXTENDED_FORMAT.format(Calendar .getInstance().getTime()); ORA_DATE_MATCHER = ORA_DATE_PATTERN.matcher(dte); ORA_DATE_MATCHER.find(); } /** * 渲染序号 * * @param ruleDef * 序号规则定义字符串 * @return 渲染后的序号值 */ public static final String render(String defName) { return render(defName, null); } /** * 渲染序号 * * @param ruleDef * 序号规则定义字符串 * @param request * 客户端请求数据 * @return 渲染后的序号值 */ public static final String render(String defName, Object bean) { reloadData(bean); String ruleDef = getGrowthFactor(defName, true); if (StringUtils.isEmpty(ruleDef)) return ""; Matcher m = COMMON_RULE_PATTERN.matcher(ruleDef); StringBuffer sb = new StringBuffer(""); String paramValue = null; while (m.find()) { String r = m.group(1); if (StringUtils.isEmpty(r)) continue; // 检查是否需要进行字串变换操作 paramValue = getFnParam(m.group(2), getMatcherValue(r)); m.appendReplacement(sb, paramValue); } m.appendTail(sb); return sb.toString(); } /** * 根据规则序号定义获取预览序号值(表单没有进行保存前显示) * * @param def * 规则定义实体对象 * @return * * @author Inkcar Nov 5, 2010 3:44:10 PM */ public static final String getPreviewSequence(String defName) { reloadData(null); // 获取已设置增长因子值的规则序号及定义 String ruleDef = getGrowthFactor(defName, false); if (StringUtils.isEmpty(ruleDef)) { return ""; } Matcher m = COMMON_RULE_PATTERN.matcher(ruleDef); StringBuffer sb = new StringBuffer(""); while (m.find()) { String r = m.group(1); if (StringUtils.isEmpty(r) || r.charAt(0) == '@') continue; m.appendReplacement(sb, getMatcherValue(r)); } m.appendTail(sb); return sb.toString(); } /** * 获取增长因子匹配 * * @param gene * 规则定义字符 * @return 匹配增长因子之后的字符 */ private static final String getGrowthFactor(String defName, boolean save) { if (StringUtils.isEmpty(defName)) { return ""; } /* * 从数据库获取规则序号定义 */ // PtSequenceDefinition def = ptSequenceDefinitionBIZ // .getPtSequenceDefinitionByName(defName); // if (def == null) { // return ""; // } // String ruleDef = def.getDefinitionRule(); /* * 从properties配置文件读取序号规则定义 */ String defineName = "sequence.define." + defName; String ruleDef = SystemGlobal.get(defineName); if (StringUtils.isEmpty(ruleDef)) { return ""; } Matcher g = GROWTH_FACTOR_PATTERN.matcher(ruleDef); StringBuffer sb = new StringBuffer(""); Integer leng = 0, value = 0; String cacheFieldName; while (g.find()) { StringBuffer sbGene = new StringBuffer(""); String strGene = g.group(2); if (!StringUtils.isEmpty(strGene)) { String[] arr = strGene.split("_"); for (int i = 0; i < arr.length; i++) { String ch = arr[i]; if (StringUtils.isEmpty(ch)) continue; sbGene.append(getMatcherValue(ch)); } } // 增长因子值最小位数 leng = Integer.valueOf(g.group(1)); // 从properties配置文件获取当前增长因子最大值 cacheFieldName = defineName + "." + sbGene.toString(); value = SystemGlobal.getInteger(cacheFieldName) + 1; // 从数据库获取增长因子最大值 // value = // ptSequenceInstanceBIZ.getGrowthFactor(def,sbGene.toString()); // 获取并更新当前因子最大值,对数据库进行操作 if (save) { // 保存到properties配置文件 SystemGlobal.set(cacheFieldName, value.toString()); // 保存到数据库 // ptSequenceInstanceBIZ.updateGrowthFactor(def, // value); } g.appendReplacement(sb, StringUtils.getFillDigits(value.toString(), leng)); } g.appendTail(sb); return sb.toString(); } /** * 匹配随机字符 * * @param gene * 随机匹配字符 * @return 匹配值 */ private static final String getRandomCharacter(String gene) { Matcher m = RANDOM_PATTERN.matcher(gene); StringBuffer sb = new StringBuffer(""); if (m.find()) { // 将随机值添加到序号值中 m.appendReplacement(sb, StringUtils.getRands(Integer.valueOf(m .group(2)), m.group(1))); return sb.toString(); } return gene; } /** * 获取规则序号匹配值 * * @param val * 匹配字符串 * @return 匹配值 */ @SuppressWarnings("unchecked") private static final String getMatcherValue(String val) { // 获取传入参数值 if (val.charAt(0) == '@') { String field = val.replace("@", ""); // 获取参数键值对象 Map bean = getRequestThread(); if (!StringUtils.isEmpty(field)) { Object value = bean.get(field); if (value == null) return ""; return value.toString(); } return ""; } Integer index = -1; // 从properties配置文件获取规则定义 String value = getPropertyName(val); try { index = Integer.valueOf(value); } catch (Exception e) { } if (index != -1) { // 获取当前操作时间指定位置值 return ORA_DATE_MATCHER.group(index); } return getRandomCharacter(val); } /** * 对指定值进行预定义的变换操作 * * @param fnName * 操作类型,如replace、substring、toLowerCase、toUpperCase、trim * @param paramValue * 操作字符值 * @return */ private static String getFnParam(String fnName, String paramValue) { if (!StringUtils.isEmpty(fnName)) { Matcher fnMatcher = COMMON_RULE_FN_PATTERN.matcher(fnName); String fn, fnParams, reValue; String[] arrParams; while (fnMatcher.find()) { if (!StringUtils.isEmpty(fnMatcher.group())) { try { fn = fnMatcher.group(1); fnParams = fnMatcher.group(2); arrParams = fnParams != null ? fnParams.split(",") : new String[] {}; reValue = arrParams.length > 1 ? arrParams[1] : ""; if ("replace".equals(fn)) { paramValue = paramValue.replaceAll(arrParams[0], reValue); } else if ("substring".equals(fn)) { Integer start = arrParams.length > 0 ? Integer .valueOf(arrParams[0]) : 0; Integer end = arrParams.length > 1 ? Integer .valueOf(arrParams[1]) : 0; if (end > 0) { paramValue = paramValue.substring(start, end); } else { paramValue = paramValue.substring(start); } } else if ("toLowerCase".equals(fn)) { paramValue = paramValue.toLowerCase(); } else if ("toUpperCase".equals(fn)) { paramValue = paramValue.toUpperCase(); } else if ("trim".equals(fn)) { paramValue = paramValue.trim(); } } catch (Exception e) { e.printStackTrace(); } } } } return paramValue; } /** * 获取当前请求线程 * * @return */ @SuppressWarnings("unchecked") private static final Map getRequestThread() { return USERDATA.get(); } }
3、测试类
package test.inkcar.sequence; import test.inkcar.sequence.preferences.SystemGlobal; import test.inkcar.sequence.utils.SequenceUtils; import junit.framework.TestCase; public class SequenceTest extends TestCase { public void testSystemGlobal() { System.out.println("读取配置:"); System.out .println(SystemGlobal.get("sequence.define.xiaoShouNo.20110701")); } public void testSequence() { System.out.println("生成序号"); System.out.println(SequenceUtils.render("xiaoShouNo")); } }
- test.rar (7.5 KB)
- 下载次数: 22
相关推荐
针对硬件绑定 软件序列号生成 , 序列号检测, 相当的好用,都加了注释
在这个“序号自动生成器.zip”压缩包中,包含了一个基于C#的源码项目,用户可以根据自己的需求进行定制,以满足特定的序号生成规则。 序号自动生成器的核心功能通常包括以下几点: 1. **序列生成策略**:序号可以...
可自动生成各类序号、密码 可设置生成规则 可定长,定位,定内容生成 可设置排除或包含字串
包括最新的sony vegas pro 11 crack
在网上搜了半天,都没有看到满意的程序。只好参照别人写的例子,自己写了。编号是按照年份和月份+三位序号自动生成的,用的是SQL server数据库,用VS2010编写的。调试已通过。希望给同为新手的各位一个参考。
递增的序号列是一种自动增长的序号,可以根据某个特定的规则或条件进行增长。例如,在管理客户信息时,可以根据客户的编号或注册时间来自动增长序号。这种序号列可以帮助我们更好地管理和分析数据。 现在,让我们来...
自动生成序号的两种方式 利用 SQL 语句自动生成序号是数据库管理系统中的一种常用技术,本文将介绍两种利用 SQL 语句自动生成序号的方式,并详细解释每种方式的实现原理和应用场景。 第一种方式:使用 row_number...
规则命名则是指用户可以设置一套命名规则,如序号、日期、特定字符串等,软件将自动按照这些规则为每个新生成的文件夹命名,确保了文件夹命名的统一性和可读性。 标签“文件夹生成”明确了该程序的主要应用场景,即...
### 昊华智能二维码生成规则详解 #### 一、引言 随着智能家居市场的快速发展,越来越多的家庭开始使用智能家居产品。为了确保这些智能设备能够被轻松识别和管理,昊华智能制定了一套详细的二维码生成规则及地址映射...
SQL Server 中按年月日生成日期型自增编码 本文档介绍了在 SQL Server 中生成日期型自增编码的方法,通过创建两个函数 `GenCustomCode` 和 `GenCustomID`,可以生成按年月日的日期型自增编码。该方法可以应用于各种...
标题“自动生成编号【sql】”所指的是一种技术,用于在数据库表中创建自动递增或基于特定规则的唯一编号。在SQL Server 2005中,我们可以使用`IDENTITY`属性来创建自动递增的整数序列,适用于主键或序列号字段。例如...
//生成最大编号 规则为当前日期+6位顺番, //没有记录时,当前日期+000001 //当前日期比从数据库取得的最大日期大时, 当前日期+000001 //当前日期等于从数据库取得最大日期,顺番+1
在本文中,我们将深入探讨如何在使用Element Plus的`el-table`组件实现树形表格时进行表单验证以及如何生成序号。`el-table`是一个强大的数据展示组件,支持多种复杂的表格布局和功能,包括树形结构。在处理树形表格...
在存储过程中,我们可以根据业务规则来生成和返回自定义格式的编号。 3. **.NET代码控制**:在.NET应用程序中,我们也可以在插入数据前计算编号,然后将生成的编号和其它数据一起插入数据库。这通常适用于复杂或...
在Spring Boot应用中,处理Excel文件的导出、导入和生成是常见...在实际开发中,可能需要根据业务需求进行更复杂的定制,如处理复杂格式、校验规则等。理解这些基础操作,可以灵活地构建满足各种需求的Excel处理功能。
- **操作步骤**:选中需要设置条件格式的序号区域,点击“开始”选项卡下的“样式”组中的“条件格式”,根据需要选择合适的规则进行设置。 - **应用场景**:例如,对于超出一定范围的序号采用不同颜色高亮显示,...
/** * 获得序列号,同时更新持久化存储中的序列 * @param current 当前的日期 * @param start 初始化的序号 * @return 所获得新的序列号 */ protected abstract int getOrUpdateNumber(Date current, int start);