2009-03-05 40 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(); 
} 
相關問題