版本号定义可以参考语义化版本 2.0.0,本文只考虑三位版本号,不考虑先行版本号和版本编译信息。具体如下:
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:
采用 主版本号.次版本号.修订号的格式,且只能使用数字,不能以0开头。
正则表达式为:
^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$
对应java程序及单元测试:
private static final String PATTERN_STR = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$";private static final Pattern VERSION_PATTERN = Pattern.compile(PATTERN_STR);/*** 是否是有效的版本号** @param input 字符串* @return 是否是有效的版本号*/public static boolean isValidVersion(String input) {if (input == null) {return false;}return VERSION_PATTERN.matcher(input).matches();}
对应单元测试代码:
private static Stream validVersionProvider() {return Stream.of("0.0.4","1.2.3","10.20.30","1.0.0","2.0.0","1.1.7","99999999999999999999999.999999999999999999.99999999999999999");}private static Stream invalidVersionProvider() {return Stream.of("1","1.2","1.2.3-0123","+invalid","invalid","alpha","01.1.1","1.01.1","1.1.01","1.2-SNAPSHOT","1.2-RC-SNAPSHOT");}@ParameterizedTest(name = "#{index} - Run test with Version = {0}")@MethodSource("validVersionProvider")void test_version_regex_valid(String inputVersion) {assertTrue(VersionUtils.isValidVersion(inputVersion));}@ParameterizedTest(name = "#{index} - Run test with Version = {0}")@MethodSource("invalidVersionProvider")void test_version_regex_invalid(String inputVersion) {assertFalse(VersionUtils.isValidVersion(inputVersion));}
参考:https://semver.org/lang/zh-CN/#spec-item-11
版本的优先层级指的是不同版本在排序时如何比较。
判断优先层级时,必须(MUST)把版本依序拆分为主版本号、次版本号、修订号后进行比较。
由左到右依序比较每个标识符,第一个差异值用来决定优先层级:主版本号、次版本号及修订号以数值比较。
例如:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。
对应java代码及单元测试代码:
/*** 比较两个版本号大小* version1比version2大返回1* version1比version2小返回-1* version1与version2相同返回0** @param version1 version1* @param version2 version2* @return 比较结果*/public static int compare(String version1, String version2) {if (!isValidVersion(version1) || !isValidVersion(version2)) {throw new RuntimeException("invalid version.");}if (version1.equals(version2)) {return 0;}String[] version1Codes = version1.split("\\.");String[] version2Codes = version2.split("\\.");for (int i = 0; i < version1Codes.length; i++) {int code1 = Integer.parseInt(version1Codes[i]);int code2 = Integer.parseInt(version2Codes[i]);if (code1 > code2) {return 1;} else if (code1 < code2) {return -1;}}return 0;}
对应单元测试代码:
@Test@DisplayName("version compare return 1")public void test_version_compare_return_1() {String version1 = "1.1.1";String version2 = "1.1.0";Assertions.assertEquals(1, VersionUtils.compare(version1, version2));version1 = "2.1.1";version2 = "1.2.0";Assertions.assertEquals(1, VersionUtils.compare(version1, version2));version1 = "10.1.1";version2 = "2.2.0";Assertions.assertEquals(1, VersionUtils.compare(version1, version2));}@Test@DisplayName("version compare return -1")public void test_version_compare_return__1() {String version1 = "1.1.1";String version2 = "1.1.2";Assertions.assertEquals(-1, VersionUtils.compare(version1, version2));version1 = "2.1.1";version2 = "2.2.0";Assertions.assertEquals(-1, VersionUtils.compare(version1, version2));version1 = "10.1.1";version2 = "11.2.0";Assertions.assertEquals(-1, VersionUtils.compare(version1, version2));}@Test@DisplayName("version compare return 0")public void test_version_compare_return_0() {String version1 = "1.1.1";String version2 = "1.1.1";Assertions.assertEquals(0, VersionUtils.compare(version1, version2));}
1. 语义化版本 2.0.0,