代码之家  ›  专栏  ›  技术社区  ›  willcodejavaforfood

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

  •  11
  • willcodejavaforfood  · 技术社区  · 16 年前

    我们的代码使用了很多系统属性,例如“java.io.tmpdir”、“user.home”、“username”等。我们在任何地方都没有为这些定义任何常量(我认为java也没有),也没有任何其他聪明的方法来处理它们,所以它们以明文形式散布在整个代码中。

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

    大家是如何使用系统属性的?

    7 回复  |  直到 16 年前
        1
  •  9
  •   Bill the Lizard    16 年前

    我会将其视为您在代码中分散的任何其他字符串常量,并为其定义一个常量变量。当然,在这种情况下,“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);
    
        2
  •  5
  •   a3.14_Infinity    10 年前

    SystemUtils Apache Commons Lang包提供的解决方案解决了这个问题。

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

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

    也许,这是一种更干净的方法。

        3
  •  4
  •   drscroogemcduck drscroogemcduck    16 年前

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

    所以可能类似于:Configuration.getTemporaryDirectory()

        4
  •  4
  •   erickson    16 年前

    由于问题标题非常宽泛,我将提出另一个在使用系统属性时应该考虑的好做法。访问系统属性可能会被拒绝 SecurityManager ,因此您可能需要通过 PrivilegedAction , 这样地:

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

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

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

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

        5
  •  4
  •   Sixro    12 年前

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

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

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

        6
  •  1
  •   jamesh    16 年前

    我会把这些当作任何其他常数来对待,可能是 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";
    }
    

    最后,我会认真考虑对属性名称本身进行命名空间设置,并使用标准的反向域名对包进行命名空间设置。这只是为了避免与第三方房产消费者发生冲突。

        7
  •  0
  •   Cody Burleson    12 年前

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

    System.getProperty(Prop.TEMPDIR);
    

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

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