使用Java系统属性的最佳实践

时间:2009-01-28 13:21:28

标签: java properties

我们的代码使用了很多系统属性,例如'java.io.tmpdir','user.home','user.name'等。我们没有为这些定义任何常量(也没有java I)思考)或处理它们的任何其他聪明的东西,所以它们在整个代码中散布着纯文本。

String tempFolderPath = System.getProperty("java.io.tmpdir");

每个人如何使用系统属性?

7 个答案:

答案 0 :(得分:8)

我会像处理代码中的任何其他字符串常量一样对待它,并为它定义一个常量变量。当然,在这种情况下,“java.io.tmpdir”不太可能改变,但你永远不会知道。 (我并不是说Sun可能会改变“java.io.tmpdir”的含义,或者它指向的系统属性,但是你可能会改变你对你需要阅读的系统属性的想法。)

如果您只在一个类中使用特定属性,那么我将在该类中定义常量。

private final String TEMPDIR = "java.io.tmpdir";

如果您在不同的类中使用相同的属性,您可能希望定义自己的静态类来保存最常用的常量。

public final Class Prop {
    public static final String TEMPDIR = "java.io.tmpdir";
    ...
}

然后,无论您需要使用该常量,只需使用

调用它
System.getProperty(Prop.TEMPDIR);

答案 1 :(得分:5)

Apache Commons Lang软件包提供的

SystemUtils解决了这个问题。

SystemUtils为大多数系统属性定义了常量,可以通过查找获得,例如:

import org.apache.commons.lang3.SystemUtils;

class Something
{
    public static void main(String[] args){     
        System.out.println(SystemUtils.JAVA_IO_TMPDIR);
    }
}

或许,这是一种更清洁的方式。

答案 2 :(得分:4)

如果你在多个地方使用它,那么编写一个类来封装读取属性和其他属性可能是个好主意。

所以可能是这样的:Configuration.getTemporaryDirectory()

答案 3 :(得分:4)

我认为在面向对象的软件中,您可能有一个对象(或方法)依赖于必须完成作业的目录。因此,您可以证明这种依赖于构造函数或方法。 之后,如果您需要该目录的默认值并且默认值来自系统属性,则可以简单地创建一个工厂方法或构造函数/方法,将较少的参数传递给另一个costrunctor /方法a:

new File(System.getProperty("java.io.tmpdir");

您不需要创建“依赖磁铁”只包含配置参数。

答案 4 :(得分:3)

由于问题标题非常广泛,我将在使用系统属性时考虑另一个好的做法。 SecurityManager可以拒绝访问系统属性,因此您可能需要通过PrivilegedAction,访问它们,如下所示:

String tmpdir = AccessController.doPrivileged(new PrivilegedAction<String>() {
  public String run() {
    return System.getProperty("java.io.tmpdir");
  }
});

当您的代码约束敏感操作时使用特权操作,以便即使恶意代码调用它也是安全的。

例如,在OutputStream open(File file)之类的方法中使用特权操作是不安全的。不受信任的代码可以调用它,并使用您的代码权限在任何地方编写任何内容。

但是,如果您的方法将应用程序的用户首选项保存到您选择的文件中,那么这可能是安全的。恶意调用者无法选择文件位置或其内容;这些是由您的代码指定的。因此,您的方法可以使用特权操作来允许由非特权代码调用它。

答案 5 :(得分:1)

我将这些视为任何其他常量,可能带有P_PROP_前缀,并将它们放在适当的常量类中。

如果你使用了很多,我甚至会考虑将它们分成PropertyNames常量类:

public final class PropertyNames
{
  private PropertyNames()
  {
     // no instantiation
  }

  public static final String P_VAR_DIRECTORY = "org.acme.app.varDir";

  public static final String P_TMP_DIRECTORY = "java.io.tmpDir";
}

最后,我会认真考虑使用用于包的标准反向域名来命名属性名称本身。这只是为了避免与第三方媒体消费者发生冲突。

答案 6 :(得分:0)

在Java中,字符串是不可变的,这意味着内存空间中的相同对象不会被覆盖;每次都会创建一个新的String。目前投票最高的建议是使用常数:

System.getProperty(Prop.TEMPDIR);

不幸的是,正在使用的常量是实际的属性键。这意味着每次进行此调用时,您将创建一个新的String对象来保存该值。在我看来,你应该使调用本身的结果保持不变:

public static final String SYS_PROP_TEMP_DIR = System.getProperty("java.io.tmpdir");