文章目录
1. 在Java程序中获取环境变量的用途
在Java程序中获取环境变量有几个常见的用途,这些用途可以帮助开发者更好地控制程序的行为,适应不同的运行环境。
以下是一些主要的用途:
- 配置敏感信息:环境变量可以用来存储数据库密码、API密钥等敏感信息,这样可以避免将这些信息硬编码到源代码中,从而提高安全性。
- 指定资源路径:在不同的环境中(如开发环境、测试环境、生产环境),应用程序可能需要访问不同位置的文件或资源。通过环境变量来指定这些路径,可以使应用程序更加灵活,易于部署到不同的环境中。
- 控制应用程序行为:环境变量可以用来开启或关闭某些功能,比如日志级别、调试模式等。这使得应用程序可以根据运行环境的不同而表现出不同的行为,有助于性能优化和故障排查。
- 集成第三方服务:当应用程序需要与第三方服务(如云存储、消息队列等)交互时,可以通过环境变量来配置服务的URL、认证信息等参数,方便地切换不同的服务提供者或实例。
- 多环境部署:在持续集成/持续部署(CI/CD)流程中,环境变量是实现自动化部署的重要工具之一。它们允许开发者定义一组通用的构建脚本,然后通过设置不同的环境变量来适应各种部署目标。
2. 环境变量与Java系统属性的区别
环境变量是操作系统级别的配置,在系统启动时设置,可以被系统中的所有进程访问(环境变量命名通常是全部使用大写字母,使用下划线 _
来分隔单词)
Java 系统属性是针对 Java 虚拟机的配置,在 Java 应用程序启动时通过 JVM 参数指定(-D
选项)
-
-D
选项是 Java 虚拟机(JVM)参数的一部分,用于配置 JVM 的行为 -
-D
是一个标识符,代表 “Define a system property”(定义一个系统属性) -
如果需要设置多个 JVM 参数,可以在命令行中多次使用
-D
选项,每个-D
选项后面跟一个键值对,用等号=
连接
java -Dparam1=value1 -Dparam2=value2 -Dparam3=value3 -jar myapp.jar
3. 如何获取环境变量
3.1 使用System.getenv()方法(只能获取环境变量)
通过 Java 内置的 System 类获取环境变量
public class GetEnv {
public static void main(String[] args) {
String javaHome = System.getenv("JAVA_HOME");
if (javaHome != null) {
System.out.println("The value of JAVA_HOME is: " + javaHome);
} else {
System.out.println("Environment variable JAVA_HOME is not set.");
}
}
}
3.2 使用System.getProperty()方法(只能获取Java系统属性)
通过 Java 内置的 System 类获取 Java 系统属性
public class GetProperty {
public static void main(String[] args) {
String serverPort = System.getProperty("server.port");
if (serverPort != null) {
System.out.println("The value of server.port is: " + serverPort);
} else {
System.out.println("Java system property server.port is not set.");
}
}
}
3.3 使用 @Value注解在Bean中获取环境变量(既可以获取环境变量,也可以获取Java系统属性)
如果环境变量和 Java 系统属性中有同名的变量,会优先使用 Java 系统属性中的变量
在 Spring 框架中可以通过 @Value
类来获取 Java 系统属性或环境变量
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class GetEnvironmentVariableTests {
@Value("${JAVA_HOME}")
private String javaHome;
@Test
public void getEnvironmentByValueAnnotation() {
System.out.println("The value of JAVA_HOME is: " + javaHome);
}
}
3.4 使用Spring框架提供的Environment类(既可以获取环境变量,也可以获取Java系统属性)
如果环境变量和 Java 系统属性中有同名的变量,会优先使用 Java 系统属性中的变量
在 Spring 框架中可以通过Environment
类来来获取 Java 系统属性或环境变量
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
@SpringBootTest
public class GetEnvironmentVariableApplicationTests {
@Autowired
private Environment environment;
@Test
public void getJavaHome() {
String javaHome = environment.getProperty("JAVA_HOME");
if (javaHome != null) {
System.out.println("The value of JAVA_HOME is: " + javaHome);
} else {
System.out.println("Environment variable JAVA_HOME is not set.");
}
}
@Test
public void getServerPort() {
String serverPort = environment.getProperty("SERVER_PORT");
if (serverPort != null) {
System.out.println("The value of SERVER_PORT is: " + serverPort);
} else {
System.out.println("Environment variable SERVER_PORT is not set.");
}
}
}
4. SpringBoot中配置的优先级顺序
以下是 SpringBoot 中配置的优先级顺序(从高到低):
- 命令行参数(Java系统属性):启动应用程序时,可以通过命令行参数(也就是Java系统属性)直接覆盖配置文件中的值
- 系统环境变量:可以通过
System.getenv()
访问的环境变量(操作系统的环境变量) - application.properties(或application.yml)文件:在
src/main/resources
目录下的配置文件 - 默认属性:SpringBoot 的默认配置(如 Tomcat 服务器默认使用的 8080 端口)
5. 补充:在application.yml文件中如何获取环境变量
以 server.port 属性为例
server:
port: ${SERVER_PORT:11024}
- 如果通过 Java 系统属性设置了
SERVER_PORT
的值,或者操作系统中有一个名为SERVER_PORT
的环境变量,那么服务器将使用这个值作为端口号 - 如果 Java 系统属性没有设置
SERVER_PORT
的值,操作系统中也没有一个名为SERVER_PORT
的环境变量,那么服务器将使用默认的 11024 端口号
6. 如何正确地设置环境变量和Java系统属性
6.1 环境变量的命名
环境变量的命名格式应该为全大写并以下划线分隔,Spring Boot 会自动将全大写并以下划线分隔的环境变量映射到其内部的配置属性
以 application.yml 文件和 server.port 属性为例,环境变量SERVER_PORT
会自动映射到 application.yml 文件中的 server.port
配置属性
如果环境变量命名为 server.port,在低版本的 SpringBoot 项目中,server.port
环境变量可能无法映射到 server.port
配置属性
server:
port: 11024
6.2 Java系统属性的命名
Java 系统属性的命名与环境变量不同,直接填写配置属性的原始名字就可以了。例如,配置 server.port
属性
-D"server.port"=11024
7. 温馨提醒
- 如果在操作系统中设置环境变量后,读取不到环境变量,可能是因为 IDEA 等开发工具有缓存,重启开发工具之后再次运行代码,就能读取到环境变量了
- 如果环境变量和 Java 系统属性中有同名的变量,会优先使用 Java 系统属性中的变量
- 如果某个 Java 系统属性命名为
xxx.xxx
形式,需要将 Java 系统属性名用双引号包裹起来 - 虽然在 IDEA 中可以直接填写
xxx.xxx
形式的 Java 系统属性,如 -Dserver.port=11024 ,但这是不规范的写法,如果是在命令行环境中,直接填写xxx.xxx
形式的 Java 系统属性可能会带来一些意想不到的问题
java -D"server.port=11024" -jar get-environment-variable-0.0.1-SNAPSHOT.jar