From 0fa5cc1e7eab968480eabd5dcb37a6fcdb971bd6 Mon Sep 17 00:00:00 2001 From: yhl452493373 Date: Fri, 11 Feb 2022 13:57:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Sequences=20parse(String?= =?UTF-8?q?=20formatted,=20String=20pattern)=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=A0=B9=E6=8D=AE=E6=A0=BC=E5=BC=8F=E5=8F=8D?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E6=A0=BC=E5=BC=8F=E5=8C=96=E5=90=8E=E7=9A=84?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B8=BA=E5=BA=8F=E5=88=97=E5=8F=B7?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 52 ++++++++++--- pom.xml | 2 +- .../yanghuanglin/seq/generator/Generator.java | 23 +++++- .../generator/impl/SequencesGenerator.java | 77 +++++++++++++++++++ .../com/yanghuanglin/seq/po/Sequences.java | 54 +++++++++++++ .../yanghuanglin/seq/po/SequencesUnlock.java | 10 +++ .../yanghuanglin/seq/po/SequencesUnused.java | 9 +++ src/test/java/SeqTest.java | 18 ++++- 8 files changed, 230 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index cd52668..80f810d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ 使用方法: -+ 在项目中放置jar包的地方把seq-1.1.0.jar、seq-1.1.0-sources.jar、seq-1.1.0-pom.xml复制过去 ++ 在项目中放置jar包的地方把seq-1.2.0.jar、seq-1.2.0-sources.jar、seq-1.2.0-pom.xml复制过去 + 在pom.xml中增加以下内容,然后执行maven命令:mvn clean ```xml @@ -18,7 +18,7 @@ com.yanghuanglin seq - 1.0.0 + 1.2.0 @@ -50,13 +50,13 @@ - ${project.basedir}/lib/seq-1.1.0.jar - ${pom.basedir}/lib/seq-1.1.0-pom.xml - ${project.basedir}/lib/seq-1.1.0-sources.jar + ${project.basedir}/lib/seq-1.2.0.jar + ${pom.basedir}/lib/seq-1.2.0-pom.xml + ${project.basedir}/lib/seq-1.2.0-sources.jar default com.yanghuanglin seq - 1.0.0 + 1.2.0 jar true @@ -340,6 +340,16 @@ public interface Generator { */ String generate(String key, String type, Integer minLength); + /** + * 将{@link #generate(String, String)}得到的序号对象格式化为补零后的序号字符串。实际上只会用到{@link Sequences#getSeq()}属性 + * + * @param sequences 生成的序号对象 + * @param minLength 序号数字最小长度 + * @param pattern 格式 + * @return 格式化后的字符串 + */ + String format(Sequences sequences, Integer minLength, String pattern); + /** * 将生成的序号对象格式化为指定格式 *

@@ -352,7 +362,7 @@ public interface Generator { * @param seq 需要格式化的序号 * @param minLength 序号最小长度,不足的会补零 * @param pattern 格式 - * @return 格式化后的字符串 + * @return 格式化后的序号字符串 */ String format(Long seq, Integer minLength, String pattern); @@ -368,11 +378,28 @@ public interface Generator { * @param seq 需要格式化的序号 * @param start 序号格式化后以什么字符串开头 * @param minLength 序号最小长度,不足的会补零 - * @param pattern 格式 - * @return 格式化后的字符串 + * @param pattern 序号格式 + * @return 格式化后的序号字符串 */ String format(Long seq, String start, Integer minLength, String pattern); + /** + * 将已格式化的序号解析为序号对象 + *

+ * 返回的序号对象{@link Sequences#getKey()}和{@link Sequences#getType()}为null,但是临时字段{@link Sequences#getYear()}、{@link Sequences#getMonth()}、{@link Sequences#getDay()}可能有值 + *

+ * 如果生成序号时,序号的key在年、月、日上有关联(如每年每月的序号要从1开始),则需要自行用序号字符串与{@link Sequences#getYear()}、{@link Sequences#getMonth()}、{@link Sequences#getDay()}进行组合,进而得到key + *

+ * 例如:SNT序号每年都从1开始,则key应该是类似SNT2021、SNT2022这种格式,而在配置中,该序号的代码只是SNT,但是由于每年都要从1开始,所有应该每年有一个key,这个key就为SNT+年份,而这个年份就是此处解析后返回的对象中的{@link Sequences#getYear()} + *

+ * 注意:序号格式和格式化后的字符串占位一定要匹配。如:处〔#year#〕#month#10801第#seq#号 对应 处〔2022〕0210801第10001号,而不能对应 处〔2022〕021110801第10001号 + * + * @param pattern 序号格式 + * @param formatted 格式化后的序号字符串 + * @return 包含了序号字符串对应年(如果有)、月(如果有)、日(如果有)、序号的序号对象,其key、type需要根据情况手动设置 + */ + Sequences parse(String pattern, String formatted); + /** * 锁定指定序号,在序号生成后,调用该序号的逻辑完成后需要执行此方法 *

@@ -401,6 +428,13 @@ public interface Generator { * @param end 结束时间 */ void release(Date begin, Date end); + + /** + * 释放指定序号。一般用于业务对象删除后,对应序号需要回收使用时。 + * + * @param sequences 需要释放的序号。一般是一个通过{@link Sequences#setKey(String)}、{@link Sequences#setType(String)}、{@link Sequences#setSeq(Long)}三方法一起手动构建或通过{@link Sequences#Sequences(String, String, Long)}构造方法构建的实例对象 + */ + void release(Sequences sequences); } ``` \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2d70714..d8453c8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.yanghuanglin seq - 1.1.0 + 1.2.0 seq seq diff --git a/src/main/java/com/yanghuanglin/seq/generator/Generator.java b/src/main/java/com/yanghuanglin/seq/generator/Generator.java index ca0a058..55e7d85 100644 --- a/src/main/java/com/yanghuanglin/seq/generator/Generator.java +++ b/src/main/java/com/yanghuanglin/seq/generator/Generator.java @@ -72,7 +72,7 @@ public interface Generator { * @param seq 需要格式化的序号 * @param minLength 序号最小长度,不足的会补零 * @param pattern 格式 - * @return 格式化后的字符串 + * @return 格式化后的序号字符串 */ String format(Long seq, Integer minLength, String pattern); @@ -88,11 +88,28 @@ public interface Generator { * @param seq 需要格式化的序号 * @param start 序号格式化后以什么字符串开头 * @param minLength 序号最小长度,不足的会补零 - * @param pattern 格式 - * @return 格式化后的字符串 + * @param pattern 序号格式 + * @return 格式化后的序号字符串 */ String format(Long seq, String start, Integer minLength, String pattern); + /** + * 将已格式化的序号解析为序号对象 + *

+ * 返回的序号对象{@link Sequences#getKey()}和{@link Sequences#getType()}为null,但是临时字段{@link Sequences#getYear()}、{@link Sequences#getMonth()}、{@link Sequences#getDay()}可能有值 + *

+ * 如果生成序号时,序号的key在年、月、日上有关联(如每年每月的序号要从1开始),则需要自行用序号字符串与{@link Sequences#getYear()}、{@link Sequences#getMonth()}、{@link Sequences#getDay()}进行组合,进而得到key + *

+ * 例如:SNT序号每年都从1开始,则key应该是类似SNT2021、SNT2022这种格式,而在配置中,该序号的代码只是SNT,但是由于每年都要从1开始,所有应该每年有一个key,这个key就为SNT+年份,而这个年份就是此处解析后返回的对象中的{@link Sequences#getYear()} + *

+ * 注意:序号格式和格式化后的字符串占位一定要匹配。如:处〔#year#〕#month#10801第#seq#号 对应 处〔2022〕0210801第10001号,而不能对应 处〔2022〕021110801第10001号 + * + * @param formatted 格式化后的序号字符串 + * @param pattern 序号格式 + * @return 包含了序号字符串对应年(如果有)、月(如果有)、日(如果有)、序号的序号对象,其key、type需要根据情况手动设置 + */ + Sequences parse(String formatted, String pattern); + /** * 锁定指定序号,在序号生成后,调用该序号的逻辑完成后需要执行此方法 *

diff --git a/src/main/java/com/yanghuanglin/seq/generator/impl/SequencesGenerator.java b/src/main/java/com/yanghuanglin/seq/generator/impl/SequencesGenerator.java index 8990d59..341e5be 100644 --- a/src/main/java/com/yanghuanglin/seq/generator/impl/SequencesGenerator.java +++ b/src/main/java/com/yanghuanglin/seq/generator/impl/SequencesGenerator.java @@ -15,12 +15,15 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.StringUtils; import javax.sql.DataSource; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class SequencesGenerator implements Generator { private final TransactionTemplate transactionTemplate; @@ -155,6 +158,80 @@ public class SequencesGenerator implements Generator { return pattern; } + @Override + public Sequences parse(String formatted, String pattern) { + //年、月、日、序号分隔特殊符号正则规则 + String splitRegString = "(" + YEAR + "|" + MONTH + "|" + DAY + "|" + SEQ + ")"; + //根据年、月、日、序号的特殊符号,对格式进行分隔,得到排除特殊符号后的字符串数组 + String[] split = pattern.split(splitRegString); + + for (String splitString : split) { + //用排除特殊符号后的字符串依次替换序号格式字符串和格式化后的序号字符串,得到纯净的序号字符串和序号格式对应关系 + pattern = pattern.replace(splitString, ""); + formatted = formatted.replace(splitString, ""); + } + + //年、月、日的数字匹配正则规则 + String yearRegStr = "\\d{4}"; + String monthRegStr = "\\d{2}"; + String dayRegStr = "\\d{2}"; + + //将序号格式分隔特殊符号字符串转为正则匹配规则 + Pattern seqPattern = Pattern.compile(splitRegString); + //对序号格式进行匹配 + Matcher matcher = seqPattern.matcher(pattern); + + //将年、月、日匹配规则字符串转为正则匹配规则 + Pattern yearPattern = Pattern.compile(yearRegStr); + Pattern monthPattern = Pattern.compile(monthRegStr); + Pattern dayPattern = Pattern.compile(dayRegStr); + + //默认的年、月、日均为空字符串 + String year = "", month = "", day = "", seq = ""; + //根据序号匹配规则字符串查找字符串分组 + while (matcher.find()) { + String group = matcher.group(); + switch (group) { + case Generator.YEAR: + //若分组为年份分组,则将年份正则匹配到的字符串赋值给year,同时把格式化后的序号字符串中,对应年的字符串替换为空字符串 + Matcher yearMatcher = yearPattern.matcher(formatted); + if (yearMatcher.find()) { + year = yearMatcher.group(); + } + formatted = formatted.replaceFirst(yearRegStr, ""); + break; + case Generator.MONTH: + //若分组为月份分组,则将月份正则匹配到的字符串赋值给month,同时把格式化后的序号字符串中,对应月的字符串替换为空字符串 + Matcher monthMatcher = monthPattern.matcher(formatted); + if (monthMatcher.find()) { + month = monthMatcher.group(); + } + formatted = formatted.replaceFirst(monthRegStr, ""); + break; + case Generator.DAY: + //若分组为日期分组,则将日期正则匹配到的字符串赋值给day,同时把格式化后的序号字符串中,对应日期的字符串替换为空字符串 + Matcher dayMatcher = dayPattern.matcher(formatted); + if (dayMatcher.find()) { + day = dayMatcher.group(); + } + formatted = formatted.replaceFirst(dayRegStr, ""); + break; + } + } + //经过以上替换后,最后剩下的为序号,这个序号可能是补零了的,需要调用Long.parseLong来去零 + seq = formatted; + + //构建一个新的序号对象 + Sequences sequences = new Sequences(); + //用获取到的年、月、日、序号给新构建的序号对象设置对应的值 + sequences.setYear(StringUtils.hasLength(year) ? Integer.valueOf(year) : null); + sequences.setMonth(StringUtils.hasLength(month) ? Integer.valueOf(month) : null); + sequences.setDay(StringUtils.hasLength(day) ? Integer.valueOf(day) : null); + sequences.setSeq(StringUtils.hasLength(seq) ? Long.parseLong(seq) : 0L); + + return sequences; + } + @Override public synchronized boolean lock(Sequences sequences) { SequencesUnlock condition = new SequencesUnlock(sequences); diff --git a/src/main/java/com/yanghuanglin/seq/po/Sequences.java b/src/main/java/com/yanghuanglin/seq/po/Sequences.java index 1d55358..9e7e0f8 100644 --- a/src/main/java/com/yanghuanglin/seq/po/Sequences.java +++ b/src/main/java/com/yanghuanglin/seq/po/Sequences.java @@ -23,6 +23,24 @@ public class Sequences { */ protected Long seq = 0L; + /** + * 临时字段,序号对应的年份(如2022年)(如果能获取到的话)。 + * 该字段仅用于解析序号字符串时,解析出对应年份,用于合成key(如:序号对应的key为SNT+年份,返回的为其年份) + */ + private transient Integer year; + + /** + * 临时字段,序号对应的月份(如2月)(如果能获取到的话)。 + * 该字段仅用于解析序号字符串时,解析出对应月份,用于合成key(如:序号对应的key为SNT+年份+月份,返回的为其月份) + */ + private transient Integer month; + + /** + * 临时字段,序号对应的日期(如1日)(如果能获取到的话)。 + * 该字段仅用于解析序号字符串时,解析出对应日期,用于合成key(如:序号对应的key为SNT+年份+月份+日期,返回的为其日期) + */ + private transient Integer day; + public Sequences() { } @@ -71,6 +89,30 @@ public class Sequences { this.seq = seq; } + public Integer getYear() { + return year; + } + + public void setYear(Integer year) { + this.year = year; + } + + public Integer getMonth() { + return month; + } + + public void setMonth(Integer month) { + this.month = month; + } + + public Integer getDay() { + return day; + } + + public void setDay(Integer day) { + this.day = day; + } + /** * 将序号增加指定步长 * @@ -91,4 +133,16 @@ public class Sequences { return String.format("%0" + minLength + "d", this.seq); return String.valueOf(this.seq); } + + @Override + public String toString() { + return "Sequences{" + + "key='" + key + '\'' + + ", type='" + type + '\'' + + ", seq=" + seq + + ", year=" + year + + ", month=" + month + + ", day=" + day + + '}'; + } } diff --git a/src/main/java/com/yanghuanglin/seq/po/SequencesUnlock.java b/src/main/java/com/yanghuanglin/seq/po/SequencesUnlock.java index e952ad5..033c718 100644 --- a/src/main/java/com/yanghuanglin/seq/po/SequencesUnlock.java +++ b/src/main/java/com/yanghuanglin/seq/po/SequencesUnlock.java @@ -34,4 +34,14 @@ public class SequencesUnlock extends Sequences { public void setCreateTime(Date createTime) { this.createTime = createTime; } + + @Override + public String toString() { + return "SequencesUnlock{" + + "key='" + key + '\'' + + ", type='" + type + '\'' + + ", seq=" + seq + + ", createTime=" + createTime + + '}'; + } } diff --git a/src/main/java/com/yanghuanglin/seq/po/SequencesUnused.java b/src/main/java/com/yanghuanglin/seq/po/SequencesUnused.java index 3cdc4bd..e18280b 100644 --- a/src/main/java/com/yanghuanglin/seq/po/SequencesUnused.java +++ b/src/main/java/com/yanghuanglin/seq/po/SequencesUnused.java @@ -16,4 +16,13 @@ public class SequencesUnused extends Sequences { this.type = sequences.getType(); this.seq = sequences.getSeq(); } + + @Override + public String toString() { + return "SequencesUnused{" + + "key='" + key + '\'' + + ", type='" + type + '\'' + + ", seq=" + seq + + '}'; + } } diff --git a/src/test/java/SeqTest.java b/src/test/java/SeqTest.java index d4ddeef..1782075 100644 --- a/src/test/java/SeqTest.java +++ b/src/test/java/SeqTest.java @@ -1,9 +1,9 @@ +import com.mysql.cj.jdbc.MysqlDataSource; import com.yanghuanglin.seq.config.GeneratorConfig; import com.yanghuanglin.seq.config.TableConfig; -import com.yanghuanglin.seq.po.Sequences; import com.yanghuanglin.seq.generator.Generator; import com.yanghuanglin.seq.generator.impl.SequencesGenerator; -import com.mysql.cj.jdbc.MysqlDataSource; +import com.yanghuanglin.seq.po.Sequences; import org.junit.Test; import java.util.HashSet; @@ -73,4 +73,18 @@ public class SeqTest { String s = "select * from sequences where `%s`=? and `%s`=?"; System.out.println(String.format(s, "key", "value")); } + + @Test + public void parseTest() { + String seqPattern = "ZZF#year##month##seq#"; + String formatted = "ZZF20220200008"; + + Sequences sequences = generator.parse(formatted, seqPattern); + + String key = "zzfCode" + sequences.getYear(); + + sequences.setKey(key); + sequences.setType("MISSION"); + System.out.println(sequences); + } }