简体   繁体   English

从类路径中的任何地方加载资源

[英]Load resource from anywhere in classpath

I have a simple java application that loads a properties file from the current package. 我有一个简单的Java应用程序,可从当前包中加载属性文件。

this.getClass().getResourceAsStream("props.properties");

This works fine when the property file I want is in the current package. 当我想要的属性文件在当前程序包中时,这可以正常工作。 However, I want to package this application as a JAR and define and override with a new properties file where I use it. 但是,我想将此应用程序打包为JAR,并在使用它的地方用新的属性文件定义和覆盖。 Is there a way to load the first resource named "props.properties" that is on the classpath? 有没有办法加载类路径上名为“ props.properties”的第一个资源?

I want it to be as easy to override the properties file via command line: 我希望通过命令行覆盖属性文件变得如此简单:

java.exe -classpath props.properties;myJar.jar com.test.MyApp

I don't want to have to unpack the JAR and modify the properties file to change something. 我不想解压缩JAR并修改属性文件以更改某些内容。 I feel like I'm missing something obvious... 我觉得我缺少明显的东西...

The javadoc for Class.getResourceAsStream() documents the lookup logic: Class.getResourceAsStream()Javadoc记录了查找逻辑:

If the name begins with a '/' ( '\/' ), then the absolute name of the resource is the portion of the name following the '/'. 如果名称以'/'开头( '\/' ),则资源的绝对名称是名称后面'/'的一部分。

Otherwise, the absolute name is of the following form: 否则,绝对名称的格式如下:
modified_package_name/name

Where the modified_package_name is the package name of this object with '/' substituted for '.' 其中modified_package_name是此对象的软件包名称,用“ /”代替'.' ( '\.' ). '\.' )。

So in other words, the resource name passed to the method should look like /com/package/p2/props.properties if the props.properties is stored in the com.package.p2 package instead of the current class's. 因此,换句话说,如果props.properties存储在com.package.p2包中而不是当前类的包中,则传递给该方法的资源名称应类似于/com/package/p2/props.properties

I'm sure it's too late for the answer but it could be interesting for googlers this small code snippet helpers to load a properties file from any where in the Classpath. 我确定答案为时已晚,但是对于Google员工来说,这个小代码段帮助程序可以从Classpath中的任何位置加载属性文件可能会很有趣。

ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (cl != null) {
        URL url = cl.getResource(CONF_PROPERTIES);
        if (url == null) {
            url = cl.getResource("/" + CONF_PROPERTIES);
        }
        if (url != null) {
            try {
                InputStream in = url.openStream();
                props = new Properties();
                props.load(in);
            } catch (IOException e) {
                // Log the exception
            } finally {
               // close opened resources
            }

        }
    }

If all else fails you could use two different file names, say props-default.properties inside myJar.jar and props.properties to override on the command-line. 如果所有其他方法均失败,则可以使用两个不同的文件名,例如props-default.properties myJar.jarprops.properties在命令行上覆盖。 In your code, you'd try loading the props.properties file first and fallback to props-default.properties if it wasn't found. 在您的代码中,您将尝试首先加载props.properties文件,如果找不到该文件,则回props-default.properties

I'm not sure, but maybe: ClassLoader.getResourceAsStream() 我不确定,但也许: ClassLoader.getResourceAsStream()

EDIT: 编辑:

I don't think this is significantly different to this.getClass().getResourceAsStream() from the question, since as mentioned you still have to get the ClassLoader you want to use to load the resource. 我认为这与问题中的this.getClass().getResourceAsStream()并没有显着区别,因为如上所述,您仍然必须获取要用于加载资源的ClassLoader。

Since you provide the resource in the -classpath in your example, it should be available from the same class loader as your "main" class (in the SUN JVM, that's sun.misc.Launcher$AppClassLoader , not sure if this can/does vary for other JVM implementations). 由于您在示例中的-classpath中提供了资源,因此应该可以从与“主”类相同的类加载器中使用该资源(在SUN JVM中为sun.misc.Launcher$AppClassLoader ,不确定是否可以这样做)因其他JVM实现而异)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM