2012-06-03 44 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