设置java系统属性的最佳实践是什么,-D或System.setProperty()?

我需要为我正在处理的RMI应用程序设置代码库,并且首先使用它成功完成了

try{ ResourceBundle config = ResourceBundle.getBundle("myApp"); String codeBaseUrl = config.getString("codeBaseUrl"); System.setProperty("java.rmi.server.codebase", codeBaseUrl); } catch (Exception e) { e.printStackTrace(); } 

然后使用

 java -Djava.rmi.server.codebase=http://192.168.1.1/path/to/codebase ... 

在命令行上。

这两种方法都允许在不需要重新编译的情况下更改代码库,但System.setProperty方法允许将代码库打包成属性文件并使用相同的启动命令。

我读过的大部分教程/文档都使用-D方法让我相信这被认为是最佳实践,但是我一直无法找到解释为什么我应该使用另一个的任何东西。

-D被认为是设置系统属性(如代码库)的最佳实践,它会带来哪些好处/它会避免哪些陷阱?

(编辑 – 我误读了这个问题)

比较两者:

  • -D是可配置的 – 它是在运行时指定的
  • 通过System.setProperty()资源包仍然是“运行时”,但它是通过一个超出启动命令的文件编辑的

首先,通过在运行时指定设置来驱动灵活行为总是优于硬编码行为(除非行为实际上不灵活 – 即除非有这样的值,否则不要使用配置)。

使用文件的主要缺点是它可能包含敏感数据,如密码,系统管理员不希望永久存放在磁盘上。 如果密码作为启动命令的一部分输入,则它是短暂的并且更加安全(会话命令历史记录不能承受)。

使用文件的好处是您可以建立正确的设置并保留在文件中。 您甚至可以通过源代码管理来管理文件。

还有另一种更安全的选择,即启动时要求在命令行输入密码,这样就不会留下任何痕迹。

我会使用System.setProperty(在应用程序的最顶层,因为对于某些属性,否则可能为时已太晚),但从配置文件中获取信息。

你几乎已经这样做了,但我也允许设置任意属性,而不仅仅是一些硬编码键。

我喜欢将它与我的应用程序已经使用的配置文件相结合,该配置文件还包含其他(nonSystem.properties)设置。 我通过在系统属性前加上-D来区分这两者(就像在命令行中一样):

  # some configuration abc = xxx # RMI settings -Djava.rmi.server.codebase = http://192.168.1.1/path/to/codebase 

将有一个默认位置来查找此属性文件,但可以通过命令行开关覆盖(以便您可以在不同的配置之间切换或轻松安装多个代码)。

拥有一个文件具有额外的好处,它也可以作为文档(关于可用的选项,默认值是什么,等等)。

我真的希望Java有一个内置工具来从属性文件中获取系统属性,以及其他JVM设置,如内存和类路径。 目前,您必须自己完成所有这些工作,无论是使用Java还是使用特定于操作系统的shell包装器。

除非有特殊原因(例如避免暴露敏感信息或防止修改),否则我建议使用“-D”选项,而不是使用System.setProperty添加属性。

  • 它更简单(代码更少)
  • 它允许以独立于应用程序的方式直接配置
  • 它避免了在应用程序代码有机会设置它们之前初始化期间读取系统属性的问题。

我的另一个建议是不要将系统属性用作大量特定于应用程序的属性的转储基础。 如果您有许多应用程序配置属性,请使用单独的Properties对象(或更复杂的东西),并从单独的属性文件(或更复杂的东西)加载它。 其他人可能不同意我的意见,但我发现这是一个更好的方法。

(但很明显,如果您使用的是查看系统属性的标准或第三方子系统,那么您需要这样做。)

因为通过在运行时传递参数,您可以轻松地为开发和生产(以及其他)环境提供单个代码库,而无需将语句硬编码到代码中。 例如,在开发中,您可能希望连接到192.168.0.1的服务器,而在生产中,您可能希望转到10.0.1.1。 为了通过使用System.setProperty进行硬编码来实现此结果,您需要具有条件语句并且可能会变得混乱。

您通常不希望为每个环境重新编译应用程序,因此通常最方便的是在运行时传递参数或使用某些类型的属性文件,该文件可以根据系统进行更改。