2

这是我项目的Maven结构

应用程序
  > 通用模块
  > webapp 模块
  > 批处理模块
 pom.xml

common-module暴露一个类Version。webapp 和批处理模块都使用此类。

该类Version有一个独特的静态方法,称为get. 它返回项目的全局版本。

全局版本存储在属性文件中。当get从批处理模块(一个独立的 java 应用程序)调用时,属性文件被成功加载。

在 webapp 中,情况有所不同。我创建了一个托管 bean VersionBean,它允许任何 JSF 页面调用该get方法。每当我使用以下其中一项

FacesContext.getCurrentInstance().getExternalContext()

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

Thread.currentThread().getClassLoader()

我永远找不到properties.file。

如何从托管 bean 加载位于 jar 文件中的属性文件 (getResourceAsStream)?

编辑
这是我根据@BalusC 和@eljunior 的建议提出的解决方案

版本Bean.java

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

版本.java

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

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

2 回答 2

11

我不确定 Maven 如何构建 WAR 以及您的属性文件的实际位置,但我至少可以知道如何ExternalContext#getResourceAsStream()Thread#getContextClassLoader()并且Class#getClassLoader()所有工作方式都不同。

  1. ExternalContext#getResourceAsStream()在 Web 内容文件夹(WAR和文件夹也驻留的位置)和Web 应用中部署的任何 JAR 文件的文件夹中
    扫描ExternalContext#getResourceAsStream()Web 应用资源。提供的路径始终与这些根文件夹相关,并且应以./WEB-INF/META-INF/META-INF/resources/WEB-INF/lib/

    InputStream input = externalContext
        .getResourceAsStream("/WEB-INF/version.properties");
    
  2. Thread#getContextClassLoader()
    对类路径 的Thread#getContextClassLoader()“根”进行操作。这涵盖了 webapp、appserver 和 JVM 的类路径所涵盖的所有文件夹。提供的路径总是相对于类路径根目录,不能/. 请注意,当属性文件包含在包中时,您应该将包结构视为带有/分隔符的文件系统路径。下面的示例假定它在 package 中com.example.version

    InputStream input = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream("com/example/version/version.properties");
    
  3. Class#getClassLoader()相对于类本身的位置进行操作
    Class#getClassLoader()提供的路径可以是相对的或绝对的。如果是相对的,那么它是相对于类本身的位置的。如果是绝对的,那么它对于类路径根是绝对的。请注意,这不一定可以访问类路径涵盖的所有其他文件夹。下面的示例假定属性文件与VersionBean类位于同一包中:

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

    或者当它在另一个包中时,例如com.example.other(注意前导/):

    InputStream input = VersionBean.class
        .getResourceAsStream("/com/example/other/version.properties");
    
于 2012-06-03T23:35:06.033 回答
0

我会将属性文件的加载委托给该类的同一个类加载器Version:在 get 方法中,使用Version.class.getResourceAsStream("yourFile.properties");.

这应该可以在可以加载 Version 类的任何地方工作,因此它也可以在 webapp 中工作(当然,前提是属性文件实际上common-module jar 文件中:)。

然后您的 VersionBean 可能是一个应用程序范围的 bean,它在初始化应用程序时刚刚加载了属性,如下所示:

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

请注意,如果您使用的是 2.0 之前的 JSF 版本,则必须在 中配置托管 bean,faces-config.xml而不是使用注解@ManagedBean@ApplicationScoped.

于 2012-06-03T21:56:30.420 回答