2012-06-03 80 views
2

這裏是我的項目加載特性從JAR文件中的文件,JSF

 
app 
    > common-module 
    > webapp-module 
    > batch-module 
pom.xml 

common-module暴露了Version類的Maven的結構。這個類被webapp和批處理模塊使用。

Version類有一個獨特的靜態方法,稱爲get。它返回項目的全球版本。

全局版本存儲在屬性文件中。當從批處理模塊(獨立的Java應用程序)調用get時,屬性文件已成功加載。

在web應用中,情況有所不同。我創建了一個託管bean VersionBean,它允許任何JSF頁面調用get方法。每當我使用以下其中一種方法時

FacesContext.getCurrentInstance().getExternalContext() 

FacesContext.getCurrentInstance().getExternalContext().getContext() 

Thread.currentThread().getClassLoader() 

我永遠無法找到properties.file。

如何從託管bean加載位於jar文件中的屬性文件(getResourceAsStream)?

編輯
這裏是我想出了基於建議從@BalusC解決方案,並@eljunior

VersionBean.java

@ManagedBean(eager=true) 
@ApplicationScoped 
public class VersionBean { 
    private String version; 
    @PostConstruct 
    public void init(){ 
     version = Version.get(); 
    } 
} 

Version.java

public class Version { 
    public static String get() { 
     InputStream is = Version.class.getResourceAsStream("/version.properties"); 

     // Read InputStream and return version string ... 
    } 
} 

回答

0

我會將屬性文件的加載委託給類Version的相同類加載器:在get方法中,使用Version.class.getResourceAsStream("yourFile.properties");

這應該在任何地方工作才能裝版類,所以它會在webapp工作太(當然,所提供的性能實際上是文件IS共模塊 jar文件裏面:)。

然後你VersionBean可能是應用範圍的bean,只是裝上初始化應用程序,像這樣的屬性:

@ManagedBean(eager=true) 
@ApplicationScoped 
public class VersionBean { 
    private String version; 
    @PostConstruct 
    public void init(){ 
     version = Version.get(); 
    } 
} 

請注意,如果您正在使用2.0之前版本的JSF,你必須在faces-config.xml中配置管理bean,而不是使用註釋@ManagedBean@ApplicationScoped

11

我不知道怎麼的Maven構建WAR和您的屬性文件是實際上位置,但我至少可以告訴如何ExternalContext#getResourceAsStream()Thread#getContextClassLoader()Class#getClassLoader()所有的工作方式不同。

  1. 的ExternalContext#的getResourceAsStream()
    ExternalContext#getResourceAsStream()掃描對網頁內容的文件夾的web應用資源(那裏的戰爭的/WEB-INF/META-INF文件夾也駐留)和部署在/WEB-INF/lib任何JAR文件/META-INF/resources文件夾該webapp。提供的路徑始終相對於那些根文件夾,並應以/開頭。

    InputStream input = externalContext 
        .getResourceAsStream("/WEB-INF/version.properties"); 
    
  2. 線程#getContextClassLoader()
    Thread#getContextClassLoader()的類路徑的 「根」 操作。這涵蓋了webapp,appserver和JVM的類路徑覆蓋的所有文件夾。提供的路徑總是相對於類路徑根,並且可以而不是/開頭。請注意,將屬性文件封裝在包中時,應該將包結構視爲文件系統路徑,並使用/作爲分隔符。以下示例假定它位於包com.example.version中。

    InputStream input = Thread.currentThread().getContextClassLoader() 
        .getResourceAsStream("com/example/version/version.properties"); 
    
  3. 類#getClassLoader()
    Class#getClassLoader()操作相對於所述類本身的位置。提供的路徑可以是相對的也可以是絕對的。如果是相對的,那麼它相對於類本身的位置。如果是絕對的,那麼它對類路徑根是絕對的。請注意,這不一定有權訪問類路徑覆蓋的所有其他文件夾。下面的示例假定屬性文件是在相同的包中VersionBean類:

    InputStream input = VersionBean.class 
        .getResourceAsStream("version.properties"); 
    

    或者當它在另一個包,例如com.example.other(注意領導/):

    InputStream input = VersionBean.class 
        .getResourceAsStream("/com/example/other/version.properties"); 
    
+0

謝謝你的解釋。我不知道這些方法的表現會如此不同。屬性文件的絕對位置如下:'/WEB-INF/lib/batch-module.jar!/ version.properties' – Stephan

+0

'Thread.currentThread()。getContextClassLoader()。getResourceAsStream(「version.properties」 )'應該這樣做。 – BalusC

+0

我很困惑。這*是*解決方案#2。 Eljunior的回答(基本上解決方案#3和我的答案一樣)假定它與類中的包相同,因爲你在JAR中的絕對位置似乎不是這種情況(因爲無包類是一種不好的做法) 。免責聲明:Maven超越了我,所以我無法從頭到尾判斷它是如何構建JAR和WAR的。 – BalusC