Answers:
您无需访问特定于Maven的文件即可获取任何给定库/类的版本信息。
您可以简单地使用getClass().getPackage().getImplementationVersion()
来获取存储在.jar文件中的版本信息MANIFEST.MF
。幸运的是,Maven足够聪明,不幸的是,默认情况下,Maven也不将正确的信息写入清单!
相反,必须修改的设置<archive>
元素maven-jar-plugin
to set addDefaultImplementationEntries
和addDefaultSpecificationEntries
to true
,如下所示:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
理想情况下,应将此配置放入公司pom
或其他基本pom中。
<archive>
元素的详细文档可以在Maven存档文档中找到。
要遵循上述答案,对于.war
工件,我发现必须将等效配置应用于maven-war-plugin
,而不是maven-jar-plugin
:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
这会将版本信息添加到MANIFEST.MF
项目的中.jar
(包含在WEB-INF/lib
中.war
)
null
尽管war文件中的MANIFEST.MF包含正确的信息,但我的结果始终是。
<archiveClasses>true</archiveClasses>
-从那时起它一直可靠地工作。
这是一种从pom.properties获取版本的方法,该方法可以从清单中获取版本
public synchronized String getVersion() {
String version = null;
// try to load from maven properties first
try {
Properties p = new Properties();
InputStream is = getClass().getResourceAsStream("/META-INF/maven/com.my.group/my-artefact/pom.properties");
if (is != null) {
p.load(is);
version = p.getProperty("version", "");
}
} catch (Exception e) {
// ignore
}
// fallback to using Java API
if (version == null) {
Package aPackage = getClass().getPackage();
if (aPackage != null) {
version = aPackage.getImplementationVersion();
if (version == null) {
version = aPackage.getSpecificationVersion();
}
}
}
if (version == null) {
// we could not compute the version so use a blank
version = "";
}
return version;
}
我花了一些时间在这里的两种主要方法上,但它们对我来说并没有解决。我正在使用Netbeans进行构建,可能还有更多正在进行中。我从Maven 3中获得了一些带有某些构造的错误和警告,但是我认为这些错误和警告很容易纠正。没关系
在DZone上的这篇文章中,我确实找到了一个看起来可维护且易于实现的答案:
我已经有一个resources / config子文件夹,并且将我的文件命名为app.properties,以更好地反映我们可能会保留在那里的东西(例如支持URL等)。
唯一需要注意的是,Netbeans发出警告,表明IDE需要过滤掉。不知道在哪里/如何。在这一点上它没有作用。如果我需要跨越那座桥梁,也许可以解决这个问题。祝你好运。
我正在使用maven-assembly-plugin
我的Maven包装。在Joachim Sauer的答案中使用Apache Maven Archiver也可能有效:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution .../>
</executions>
</plugin>
由于归档器是maven共享组件之一,因此它可以被多个maven构建插件使用,如果引入了两个或多个插件(包括archive
内部配置),它们也可能会发生冲突。
要使它在Eclipse和Maven构建中运行,您应该按照其他答复中的描述添加addDefaultImplementationEntries
和addDefaultSpecificationEntries
pom条目,然后使用以下代码:
public synchronized static final String getVersion() {
// Try to get version number from pom.xml (available in Eclipse)
try {
String className = getClass().getName();
String classfileName = "/" + className.replace('.', '/') + ".class";
URL classfileResource = getClass().getResource(classfileName);
if (classfileResource != null) {
Path absolutePackagePath = Paths.get(classfileResource.toURI())
.getParent();
int packagePathSegments = className.length()
- className.replace(".", "").length();
// Remove package segments from path, plus two more levels
// for "target/classes", which is the standard location for
// classes in Eclipse.
Path path = absolutePackagePath;
for (int i = 0, segmentsToRemove = packagePathSegments + 2;
i < segmentsToRemove; i++) {
path = path.getParent();
}
Path pom = path.resolve("pom.xml");
try (InputStream is = Files.newInputStream(pom)) {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(is);
doc.getDocumentElement().normalize();
String version = (String) XPathFactory.newInstance()
.newXPath().compile("/project/version")
.evaluate(doc, XPathConstants.STRING);
if (version != null) {
version = version.trim();
if (!version.isEmpty()) {
return version;
}
}
}
}
} catch (Exception e) {
// Ignore
}
// Try to get version number from maven properties in jar's META-INF
try (InputStream is = getClass()
.getResourceAsStream("/META-INF/maven/" + MAVEN_PACKAGE + "/"
+ MAVEN_ARTIFACT + "/pom.properties")) {
if (is != null) {
Properties p = new Properties();
p.load(is);
String version = p.getProperty("version", "").trim();
if (!version.isEmpty()) {
return version;
}
}
} catch (Exception e) {
// Ignore
}
// Fallback to using Java API to get version from MANIFEST.MF
String version = null;
Package pkg = getClass().getPackage();
if (pkg != null) {
version = pkg.getImplementationVersion();
if (version == null) {
version = pkg.getSpecificationVersion();
}
}
version = version == null ? "" : version.trim();
return version.isEmpty() ? "unknown" : version;
}
如果您的Java构建将目标类放置在“目标/类”之外的其他位置,那么您可能需要调整segmentsToRemove的值。
System.getProperty("user.dir")/pom.xml
?我很确定,除了WTP以外,它也将用于其他方面。
.getResource()
或.getResourceAsStream()
。
在我的Spring Boot应用程序上,从接受的答案开始一直有效的解决方案一直有效,直到我最近将jdk更新到版本12。也尝试了所有其他答案,并且无法解决该问题。
那时,我将以下行添加到了我的spring boot应用程序的第一类中,紧随注解之后 @SpringBootApplication
@PropertySources({
@PropertySource("/META-INF/maven/com.my.group/my-artefact/pom.properties")
})
稍后,我将使用以下内容从属性文件中获取值,无论该类是我想要使用其值的任何类,并appVersion
获取项目版本给我:
@Value("${version}")
private String appVersion;
希望能对某人有所帮助。
一个与Maven兼容并适用于任何(因此也是第三方)类的简单解决方案:
private static Optional<String> getVersionFromManifest(Class<?> clazz) {
try {
File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
if (file.isFile()) {
JarFile jarFile = new JarFile(file);
Manifest manifest = jarFile.getManifest();
Attributes attributes = manifest.getMainAttributes();
final String version = attributes.getValue("Bundle-Version");
return Optional.of(version);
}
} catch (Exception e) {
// ignore
}
return Optional.empty();
}
带有maven项目的war文件中的EJB的Java 8变体。在EAP 7.0上测试。
@Log4j // lombok annotation
@Startup
@Singleton
public class ApplicationLogic {
public static final String DEVELOPMENT_APPLICATION_NAME = "application";
public static final String DEVELOPMENT_GROUP_NAME = "com.group";
private static final String POM_PROPERTIES_LOCATION = "/META-INF/maven/" + DEVELOPMENT_GROUP_NAME + "/" + DEVELOPMENT_APPLICATION_NAME + "/pom.properties";
// In case no pom.properties file was generated or wrong location is configured, no pom.properties loading is done; otherwise VERSION will be assigned later
public static String VERSION = "No pom.properties file present in folder " + POM_PROPERTIES_LOCATION;
private static final String VERSION_ERROR = "Version could not be determinated";
{
Optional.ofNullable(getClass().getResourceAsStream(POM_PROPERTIES_LOCATION)).ifPresent(p -> {
Properties properties = new Properties();
try {
properties.load(p);
VERSION = properties.getProperty("version", VERSION_ERROR);
} catch (Exception e) {
VERSION = VERSION_ERROR;
log.fatal("Unexpected error occured during loading process of pom.properties file in META-INF folder!");
}
});
}
}