在Java中使用环境变量的详细教程

815 阅读5分钟

环境变量是配置Java应用程序的一个很好的方法,而不必在代码中明确地存储设置,如数据库和缓存服务器,或第三方的API。

将这种设置保留在代码之外有几个明显的优势:

  • 避免了在设置改变时更新和重新编译代码的需要
  • 有助于防止暴露敏感的凭证,如用户名和密码,以及部署令牌。
  • 你可以在多个环境中部署相同的代码

在这篇短文中,我将向你展示一些在Java中使用环境变量的方法。

如何在Java中访问环境变量

最常见的方法之一是使用System.getenv(),它接受一个可选的String 参数。根据是否传递了String 参数,从该方法返回不同的值。具体来说。

如果传递了一个String ,并且它与内部环境Map 中的一个键相匹配,那么它的值将被返回。如果没有找到匹配的键,则返回null 。如果没有传递一个String 参数,那么将返回一个包含所有环境变量及其值的只读java.util.Map 。地图的键是环境变量的名称,它的值是数值。

请记住,不同的平台有不同的操作方式,例如,在UNIX、Linux和macOS上,环境变量是区分大小写的,而在Microsoft Windows上则不是

下面,你可以看到一个例子,说明如何使用该方法来检索LinuxSHELL 环境变量(其中包含用户的shell):

package com.settermjd.twilio.envvars;

public class Main {
    public static void main(String[] args) {
        System.out.println(
            String.format("The current shell is: %s.", System.getenv("SHELL"))
        );
    }
}

如果你想提供一个默认值,请按如下方法调用System.genenv()

System.getenv().getOrDefault("SHELL", "/bin/bash")

如何设置环境变量

除了阅读环境变量外,知道如何设置它们也很有帮助。我不会说得太详细,而是坚持说一些基本的东西。然而,如果你想更深入地了解它们,Dominik Kundel已经写了一篇关于它们的详细博文

UNIX、Linux和macOS

在UNIX、Linux和macOS上,环境变量可以通过三种核心方式设置。

对当前会话和所有子进程可用

你可以初始化环境变量,使其对当前会话可用,包括当前会话在当前会话中启动的任何会话,以及在当前会话中启动的任何进程,通过使用内置的导出命令,如下面的例子:

export USER_ID=1

以这种方式设置环境变量并不是永久性的。如果你想永久地设置一个环境变量,你需要在全系统的启动文件*/etc/profile中设置它,或者在用户特定的启动文件中设置,即~/.bash_profile*、~/.bash_login~/.profile

对当前会话可用

你可以初始化一个环境变量,使其对当前会话可用,但不对任何子进程可用,如下面的例子,不使用export 命令:

USER_ID=1

对一个特定的进程可用

最后,你可以初始化一个环境变量,使其只对一个特定的进程可用。当只有那个进程需要这个变量时,这很有帮助。你可以像下面的例子那样,在启动所需进程时初始化它:

USER_ID=1 retrieveUserDetails

微软视窗

在微软视窗中,设置环境变量的方法有些不同。你可以通过控制面板设置它们,也可以在命令提示符或PowerShell控制台中设置它们。下面有后两者的例子:

# Set USER_ID in the Windows Command Prompt
set USER_ID=1

# Set USER_ID in the Windows PowerShell console
$Env:USER_ID = 1

使用.env文件

虽然通过这种方式设置环境变量可能非常有效,但它也可能很快变得很麻烦。例如,通过在操作系统的shell中设置它们,没有具体的应用程序需要的变量列表,也没有关于变量的用途或必须是什么数据类型的信息。

鉴于此,除其他原因外,The 12-Factor App建议将配置与代码严格分开。这种做法很快就在整个开发者社区流行起来,通常是通过使用*.env*(dotenv)文件。这些是纯文本文件,存储了一个键/值对的列表,定义了应用程序工作所需的环境变量,如下例所示:

USER_ID=1
TWILIO_AUTH_TOKEN=1234567890987654321

为了简化项目的启动,出现了另一种常见的做法,即在项目中包括一个*.env.example文件,其中包含所有的键,但没有它们的值。当一个新的开发者开始工作时,他们会复制这个文件,将其命名为.env*,并为适用于他们本地开发环境的每个键设置值。

读取.env文件

假设上面的例子是我们项目的*.env*文件,我们可以使用dotenv-java这样的包来使这些变量对我们的应用程序可用。

如果你是用Kotlin开发的,你可以使用dotenv-kotlin

你可以在下面的代码示例中看到一个使用该包的例子:

package com.settermjd.twilio.envvars;

import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvException;

public class Main {
    public static void main(String[] args) {
        Dotenv dotenv = null;
        dotenv = Dotenv.configure().load();
        System.out.println(String.format(
            "Hello World. Shell is: %s. Name is: %s",
            System.getenv("SHELL"),
            dotenv.get("NAME")
        ));
    }
}

代码初始化了一个新的Dotenv 对象,dotenv,并调用Dotenv.configure().load() ,以读取位于项目根目录下的*.env*中的环境变量。之后,dotenv.get() ,以检索传递给它的String 对象的值。如果没有找到匹配的键,该方法返回null

如果需要,你可以提供一个默认值作为该方法的第二个参数。

关于.env文件安全的说明

重要的是要记住,如果敏感数据被存储在*.env中,它一定不能被存储在版本控制之下。如果发生这种情况,那么使用dotenv文件的所有安全优势都会丧失。这就是为什么通常要把它们从版本控制中排除,比如在使用Git时,把.env*(以及文件名的变化)加入项目的.gitignore文件。

这就是如何在Java中处理环境变量的问题

我希望这篇文章能帮助你理解如何在你的Java项目中使用环境变量。

你还有其他使用环境变量的方法吗?我很想知道!