2009-03-05 35 views
45

我有一个包含清单文件的web应用程序,我在其中编写了我的应用程序的当前版本。清单文件是正确创建的,但是当我在运行时尝试读取它时,我得到了一些奇怪的副作用。我在清单读取代码是这样的:如何读取运行在apache tomcat中的webapp的清单文件?

InputStream manifestStream = Thread.currentThread() 
           .getContextClassLoader() 
           .getResourceAsStream("META-INFFFF/MANIFEST.MF"); 
    try { 
     Manifest manifest = new Manifest(manifestStream); 
     Attributes attributes = manifest.getMainAttributes(); 
     String impVersion = attributes.getValue("Implementation-Version"); 
     mVersionString = impVersion; 
    } 
    catch(IOException ex) { 
     logger.warn("Error while reading version: " + ex.getMessage()); 
    } 

当我附上蚀到tomcat,我看到上面的代码工作,但它似乎变得比我预期的,不同的清单文件,该文件我可以告诉,因为ant版本和构建时间戳都是不同的。然后,我把“META-INFFFF”放在那里,上面的代码仍然有效!这意味着我正在阅读其他清单,而不是我的。我也试过

this.getClass().getClassLoader().getResourceAsStream(...) 

但是结果是一样的。从tomcat运行的webapp内部读取清单文件的正确方法是什么?

编辑:感谢您的建议。另外,我应该注意我在am下运行tomcat standalone;我从命令行启动它,然后在Eclipse的调试器中附加到正在运行的实例。这不应该有所作为,应该吗?

+0

@PascalThivent的回答是正确的。如果你的MANIFEST不存在(例如:IDE),那么添加一些异常处理,它应该是A1。 – jmelanson 2013-10-09 19:47:25

+0

这种普遍的方法帮助我: [http://stackoverflow.com/a/29103019/3158918] – user3158918 2015-03-27 17:36:08

回答

1

不知道如何读取它的“官方”方式,但是如果MANIFEST.MF无法正确加载为资源,那么试图从“ServletContext.getRealPath()”派生它的路径在你的应用程序中定义的一些网络路径?

构建过程中,通过蚂蚁将应用程序版本写入其他位置(WEB-INF/classes中的属性文件)也是我想到的另一个解决方案。

86

也许你的副作用来自于这样一个事实,即几乎所有的罐子都包含MANIFEST.MF,而你没有找到合适的瓶子。读取来自Web应用程序的MANIFEST.MF,我会说:

ServletContext application = getServletConfig().getServletContext(); 
InputStream inputStream = application.getResourceAsStream("/META-INF/MANIFEST.MF"); 
Manifest manifest = new Manifest(inputStream); 

请注意,从Eclipse中运行Tomcat是不一样的单独运行Tomcat像Eclipse与类加载器播放。

+1

事实上,战争清单不会在类路径。 – 2009-03-05 16:52:09

2

类加载器工作的默认方式是在尝试查找自己的资源之前先推迟父类。所以如果父类加载器有任何可用的清单,那就是你会得到的。实际上,应用程序服务器不一定这样做,以允许应用程序覆盖库的版本。此外,班级装载者可以具有多个瓶子并因此具有多个清单。

它可能能够获取您的唯一命名资源之一的资源URL。打开一个连接。投掷到JarURLConnection。获取JarFile。从中加载清单。这可能行不通,特别是如果Tomcat爆发战争。

[更新]当然,war文件本身不在类路径中。类路径将具有类似于WEB-INF/lib /(.jar |.zip)和WEB-INF/classes /的内容。从ServletContext获取资源应该可行。

最佳解决方案:做一些不同的事情。:)

10

晚了一点,但是这对我的作品(在Glassfish的网站申请)

Properties prop = new Properties(); 
prop.load(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF")); 
System.out.println("All attributes:" + prop.stringPropertyNames()); 
System.out.println(prop.getProperty("{whatever attribute you want}")); 
3

尝试使用jcabi-manifests,做所有这种负载为你工作。例如:

String version = Manifests.read("My-Version"); 

负荷My-Version从可用MANIFEST.MF文件中的一个属性。

重要一提的是(更多细节here)在大多数web容器当前线程类加载器是不一样的servlet上下文类加载器。这就是为什么你要你的servlet上下文追加到寄存器在运行时(more info):

Manifests.append(servletContext); 

此外,检查了这一点:在服务器应用程序根目录中http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

2

的权利清单。 找出根器件的应用,例如通过找出你的类的类路径:

String rootPath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath() 

然后替换上面的创办路径的路径:Glassfish的例子:

/applications/<webProject>/META-INF/MANIFEST.MF 

它为我工作。

0

这是我做的打印各种版本的日志文件。我已经硬编码的扩展路径,但应用程序可能servletContext.getRealPath("/")阅读完整路径WebApp文件夹。可能会打印库文件或lib文件夹中的所有内容。

// print library versions (jersey-common.jar, jackson-core-2.6.1.jar) 
try { 
    List<String> jars = Arrays.asList("jersey-common", "jackson-core", "openjpa", "mylib"); 
    StringBuilder verbuf = new StringBuilder(); 
    for(File file : new File("/opt/tomcat/webapps/myapp/WEB-INF/lib/").listFiles()) { 
     String name = file.getName(); 
     if (file.isDirectory() || !file.isFile() || !name.endsWith(".jar")) continue; 
     name = name.substring(0, name.length()-4); 
     boolean found = jars.contains(name); 
     if (!found) { 
      int idx = name.lastIndexOf('-'); 
      if (idx>0) 
       found = jars.contains(name.substring(0, idx)); 
     } 
     if (!found) continue; 

     JarFile jarFile = new JarFile(file, false); 
     try { 
      String ver; 
      Manifest mf = jarFile.getManifest(); 
      if (mf!=null) { 
       ver = mf.getMainAttributes().getValue("Bundle-Version"); 
       if (ver==null || ver.isEmpty()) 
        ver = mf.getMainAttributes().getValue("Implementation-Version"); 
      } else ver=null; 
      if (verbuf.length()>0) verbuf.append(", "); 
      verbuf.append(name + "=" + (ver!=null?ver:""));       
     } finally { 
      jarFile.close(); 
     } 
    } 
    System.out.println(verbuf.toString()); 
} catch(Exception ex) { 
    ex.printStackTrace(); 
} 
相关问题