Java 阅读一个类的jar版本

Java 阅读一个类的jar版本,java,jar,version,wildfly,manifest,Java,Jar,Version,Wildfly,Manifest,对于webservice客户端,我希望使用jar文件中的实现标题和实现版本作为用户代理字符串。问题是如何读取jar的清单 这个问题已经被问了很多次,但是答案似乎不适用于我。(例如) 问题是,简单地读取/META-INF/MANIFEST.MF几乎总是给出错误的结果。在我的例子中,它几乎总是指JBoss 中提出的解决方案 这对我来说是有问题的,因为你必须硬编码库名来停止迭代,然后它仍然可能意味着同一个库的两个版本在类路径上,你只返回第一个-不一定是正确的-点击 解决方案 似乎只适用于jar://u

对于webservice客户端,我希望使用jar文件中的实现标题和实现版本作为用户代理字符串。问题是如何读取jar的清单

这个问题已经被问了很多次,但是答案似乎不适用于我。(例如)

问题是,简单地读取/META-INF/MANIFEST.MF几乎总是给出错误的结果。在我的例子中,它几乎总是指JBoss

中提出的解决方案 这对我来说是有问题的,因为你必须硬编码库名来停止迭代,然后它仍然可能意味着同一个库的两个版本在类路径上,你只返回第一个-不一定是正确的-点击

解决方案 似乎只适用于jar://url,而在JBoss中,应用程序类加载器生成vfs://url时,jar://url完全失败

类中的代码有没有办法找到自己的清单

我尝试了上面提到的项目,这些项目在从java命令行运行的小型应用程序中运行得很好,但是我希望有一个可移植的解决方案,因为我无法预测我的库以后将在哪里使用

public static Manifest getManifest() {
    log.debug("getManifest()");
    synchronized(Version.class) {
        if(manifest==null) {
            try {
                // this works wrongly in JBoss
                //ClassLoader cl = Version.class.getProtectionDomain().getClassLoader();
                //log.debug("found classloader={}", cl);
                //URL manifesturl = cl.getResource("/META-INF/MANIFEST.MF");

                URL jar = Version.class.getProtectionDomain().getCodeSource().getLocation();
                log.debug("Class loaded from {}", jar);

                URL manifesturl = null;
                switch(jar.getProtocol()) {
                    case "file":
                        manifesturl = new URL(jar.toString()+"META-INF/MANIFEST.MF");
                        break;
                    default:
                        manifesturl = new URL(jar.toString()+"!/META-INF/MANIFEST.MF");
                }


                log.debug("Expecting manifest at {}", manifesturl);
                manifest = new Manifest(manifesturl.openStream());
            }
            catch(Exception e) {
                log.info("Could not read version", e);
            }
        }
    }
代码将检测正确的jar路径。我假设通过修改url以指向清单将得到所需的结果,但我得到以下结果:

Class loaded from vfs:/C:/Users/user/Documents/JavaLibs/wildfly-18.0.0.Final/bin/content/webapp.war/WEB-INF/lib/library-1.0-18.jar
Expecting manifest at vfs:/C:/Users/user/Documents/JavaLibs/wildfly-18.0.0.Final/bin/content/webapp.war/WEB-INF/lib/library-1.0-18.jar!/META-INF/MANIFEST.MF
Could not read version: java.io.FileNotFoundException: C:\Users\hiran\Documents\JavaLibs\wildfly-18.0.0.Final\standalone\tmp\vfs\temp\tempfc75b13f07296e98\content-e4d5ca96cbe6b35e\WEB-INF\lib\library-1.0-18.jar!\META-INF\MANIFEST.MF (The system cannot find the path specified)
我检查了该路径,似乎连jar的第一个URL(通过Version.class.getProtectionDomain().getCodeSource().getLocation()获得)都已经错了。它应该是C:\Users\user\Documents\JavaLibs\wildfly-18.0.0.Final\standalone\tmp\vfs\temp\tempfc75b13f07296e98\content-e4d5ca96cbe6b35e\WEB-INF\lib\library-1.0.18.jar


所以这甚至可能指向Wildfly中的一个问题?

我似乎在这里找到了一些合适的解决方案:

因此,最终这段代码可以在JBoss中显示jar的正确版本(至少):

this.getClass().getPackage().getImplementationTitle();
this.getClass().getPackage().getImplementationVersion();

希望我下次搜索时能找到这个答案…

如果您的代码在
.jar
中,而
.war
中呢?在
.ear
中的
.war
中的
.jar
怎么样?如果它在一个不是Wildfly的服务器中,因此有一个完全不同的类加载设置,或者根本不在
.jar
中,该怎么办?我用过类似的方法。如果您建议的方案都有问题,那么函数类是什么。getProtectionDomain().getCodeSource().getLocation();那你打算回来吗?不知何故,我相信它的实现中有一个bug,因为我希望它指向类加载的源代码,而不是其他路径。这是我的误解还是Wildfly的胡闹行为?不过,我会仔细看看你的插件。谢谢分享。:-)