public final class Version {
private Version() {}
private static final Logger logger = LoggerFactory.getLogger(Version.class);
private static final String VERSION = getVersion(Version.class, "2.0.0");
private static final boolean INTERNAL = hasResource("com/xxx/xxx.class");
private static final boolean COMPATIBLE = hasResource("com/xxx/xxx.class");
static {
// 检查是否存在重复的jar包
Version.checkDuplicate(Version.class);
}
public static String getVersion(){
return VERSION;
}
public static boolean isInternalVersion() {
return INTERNAL;
}
public static boolean isCompatibleVersion() {
return COMPATIBLE;
}
private static boolean hasResource(String path) {
try {
return Version.class.getClassLoader().getResource(path) != null;
} catch (Throwable t) {
return false;
}
}
public static String getVersion(Class<?> cls, String defaultVersion) {
try {
// 首先查找MANIFEST.MF规范中的版本号
String version = cls.getPackage().getImplementationVersion();
if (version == null || version.length() == 0) {
version = cls.getPackage().getSpecificationVersion();
}
if (version == null || version.length() == 0) {
// 如果规范中没有版本号,基于jar包名获取版本号
CodeSource codeSource = cls.getProtectionDomain().getCodeSource();
if(codeSource == null) {
logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion);
}
else {
String file = codeSource.getLocation().getFile();
if (file != null && file.length() > 0 && file.endsWith(".jar")) {
file = file.substring(0, file.length() - 4);
int i = file.lastIndexOf('/');
if (i >= 0) {
file = file.substring(i + 1);
}
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
}
while (file.length() > 0 && ! Character.isDigit(file.charAt(0))) {
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
} else {
break;
}
}
version = file;
}
}
}
// 返回版本号,如果为空返回缺省版本号
return version == null || version.length() == 0 ? defaultVersion : version;
} catch (Throwable e) { // 防御性容错
// 忽略异常,返回缺省版本号
logger.error("return default version, ignore exception " + e.getMessage(), e);
return defaultVersion;
}
}
public static void checkDuplicate(Class<?> cls, boolean failOnError) {
checkDuplicate(cls.getName().replace('.', '/') + ".class", failOnError);
}
public static void checkDuplicate(Class<?> cls) {
checkDuplicate(cls, false);
}
public static void checkDuplicate(String path, boolean failOnError) {
try {
// 在ClassPath搜文件
Enumeration<URL> urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path);
Set<String> files = new HashSet<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String file = url.getFile();
if (file != null && file.length() > 0) {
files.add(file);
}
}
}
// 如果有多个,就表示重复
if (files.size() > 1) {
String error = "Duplicate class " + path + " in " + files.size() + " jar " + files;
if (failOnError) {
throw new IllegalStateException(error);
} else {
logger.error(error);
}
}
} catch (Throwable e) { // 防御性容错
logger.error(e.getMessage(), e);
}
}
}
分享到:
相关推荐
Java工具类代码集合是Java开发中非常重要的组成部分,它们提供了许多通用的功能,使得开发者能够更加高效地编写代码,避免重复劳动。在这个集合中,我们通常会看到各种实用的方法,涵盖字符串处理、数组操作、日期...
4. **重复的代码(Duplicate Code)**:PMD可以检测出代码中重复的部分,鼓励开发者将重复代码抽象成可重用的方法或类,以提高代码复用性。 5. **无效的空检查**:如果检测到对null对象的空检查,但该对象在检查之前...
- **重构建议**:提供自动化重构的建议,如提取重复代码,简化调用链,优化接口设计等。 JavaParser库还提供了其他功能,例如修改和生成新的Java源代码。结合其他工具和框架,如Lombok或ASM,可以实现更高级的代码...
这个压缩包文件“Collection”很可能包含了关于Java集合类的一些示例代码,这些代码可以用于理解和学习如何在实际项目中应用这些集合。 Java集合框架主要由两个接口层次构成:Collection和Map。Collection是所有单...
本Java数独游戏程序通过Swing框架构建了一个图形界面,用户可以通过点击按钮和选择菜单项来生成新的数独题目、查看答案、获取提示等操作。程序还支持自定义难度等级,使得游戏更具挑战性和趣味性。此外,通过实现...
- `Class` 类允许运行时检查和操作类的信息,如获取构造函数、方法和字段。 - `newInstance()` 方法可以动态创建对象,`getMethod()` 和 `invoke()` 用于调用方法。 8. **IO 流和 NIO**: - Java I/O 流提供了...
继承允许子类继承父类的属性和方法,减少代码重复。多态是指同一种行为在不同对象上有不同的表现形式,是Java实现抽象和泛化的关键。 6. **异常处理**:Java提供了异常处理机制,通过`try-catch-finally`块捕获和...
以上工具类在实际开发中都有着广泛的应用,它们提高了代码的可复用性和可维护性,减少了重复的工作,使得程序员能够更专注于业务逻辑的实现。通过熟练掌握和使用这些工具类,可以提升Java开发的效率和质量。
Java日常处理工具类是开发过程中不可或缺的部分,它们通常包含了各种常用功能的静态方法,能够极大地提高开发效率,减少代码重复。Part1中的"java日常处理工具类part1-代码"很可能是对Java基础工具类的一个初步介绍...
总结来说,数据库连接池通过Java代码实现的核心包括连接池的初始化、连接的获取与释放、以及资源的管理和监控。通过自定义连接池,我们可以控制连接的生命周期,优化资源使用,从而提高应用的性能和稳定性。在实际...
在这个场景中,"java中的一个简单游戏代码"可能是指一个用Java编写的教学示例,它可能包含了一个获取随机不重复数字的算法。这个特性在很多游戏中非常常见,比如抽奖、猜数字等类型的游戏。 首先,我们来看一下如何...
- 使用工具类可以减少重复代码,提高代码质量。 - 在处理特定问题时,如字符串格式化、日期转换等,可以快速找到相应的工具方法。 - 通过引入第三方工具库,可以利用其封装好的复杂功能,节省开发时间。 总的来...
Java开发工具代码库是Java程序员日常工作中不可或缺的资源集合,它包含了各种常用的功能模块和工具类,旨在提高开发效率,减少重复劳动。这个代码库通常会涵盖字符串处理、日期时间操作、集合操作、IO流、网络通信、...
【JAVA斗地主代码模拟】是一个实用的教学案例,旨在帮助学习者深入理解和运用Java编程语言中的Map数据结构。斗地主是一种在中国广受欢迎的扑克游戏,它的规则复杂且有趣,涉及策略、概率和技巧。在Java中实现斗地主...
PMD通过定义一系列规则来检查代码,这些规则涵盖了设计、效率、命名规范、重复代码等多个方面,为编写整洁、高效的代码提供了有力支持。 **PMD的工作原理** PMD通过解析Java源代码文件,生成抽象语法树(Abstract ...
8. **反射**:Java反射API允许在运行时动态获取类的信息,包括类名、字段、方法等,并能动态创建对象、调用方法。这对于框架开发、元编程和插件系统非常有用。 9. **JVM内部机制**:了解Java虚拟机的工作原理,如...
当提到"SQL自动生成Java代码",通常是指通过执行特定的SQL查询,自动生成对应的Java实体类,这些实体类包含了字段(对应数据库表的列)和注解(用于ORM框架识别和映射)。例如,`@Entity`表示这是一个实体类,`@...
本资料“Java集合详解代码.zip”涵盖了Java集合框架的主要组成部分,包括List、Set、Map以及Collections工具类,通过代码实现来帮助理解和掌握这些概念。 1. **List接口**:List是有序的集合,允许重复元素,支持...
2. **时间工具类(TimeUtil.java)**:这类工具类主要用于处理时间和日期,可能包括获取当前时间、时间戳转换、日期格式化、时间间隔计算等功能。在处理与时间相关的业务逻辑时,这些方法非常实用。 3. **日期工具类...
类装载是Java虚拟机中一个至关重要的过程,它不仅决定了类如何被加载到内存中,还涉及到一系列的安全检查和初始化操作。通过深入了解类装载的过程和机制,开发者可以更好地利用这一特性来优化和增强Java应用程序的...