Properties类、加载properties文件、加载动态库、classpath

百科:

.properties - 维基百科,自由的百科全书

Properties类

Properties 类表示一组持久的属性。 属性可以保存到流或从流加载。属性列表中的每个键及其对应的值都是一个字符串。继承 Hashtable 。线程安全。更多解释请查看源码注释。

Java Properties 类 - 菜鸟

使用Properties - 廖雪峰

Properties的load方法

部分方法:

1
2
3
4
5
6
System.getProperties().getProperty(String key)
System.getProperties().setProperty(String key, String value) // 相当于一个静态变量

// 加载配置文件,设置或更新键值
System.getProperties().load(InputStream inStream)
System.getProperties().load(Reader reader)

System类

Java System类

功能

  • 获取标准输入、标准输出、错误输出流;
  • 访问系统环境变量、JVM属性、其他额外设置的属性;
  • 加载动态库的方法;
  • 快速复制数组的一部分的实用方法。 Java - 数组拷贝的几种方式

部分方法:

System.load 和 System.loadLibrary详解

1
2
3
4
5
6
7
8
9
System.getProperties()
System.setProperties(Properties propes)

System.getProperty(String key)
System.setProperty(String key, String value) // 相当于一个静态变量

// 加载动态库
System.load(String filename)
System.loadLibrary(String libname)

示例

datasource.properties 文件内容如下:

1
2
3
4
db.driverClassName=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@192.168.0.3:1521:orcl
db.username=earth
db.password=123456

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class Test {
public static void main(String[] args) throws IOException {

Properties properties = System.getProperties();
printProp01(properties);
System.out.println("-------------------------------------------------");

// 设置 Properties 为空。使用新的 Properties 需重新获取。
System.setProperties(new Properties());
properties = System.getProperties();
printProp01(properties);
System.out.println("-------------------------------------------------");

System.setProperty("country", "中国");
System.out.println(properties.getProperty("country"));
properties.setProperty("nation", "汉族");
System.out.println(System.getProperty("nation"));
printProp01(properties);
System.out.println("-------------------------------------------------");

// 加载配置文件,设置或更新键值
properties.load(new InputStreamReader(new FileInputStream("D:\\datasource.properties"), "UTF-8"));
properties.load(new FileInputStream("D:\\datasource.properties"));
printProp01(properties);
System.out.println("-------------------------------------------------");

// 加载动态库 略...
}

/**
* 输出properties的key和value
*/
public static void printProp01(Properties properties) {
for (String key : properties.stringPropertyNames()) {
System.out.println(key + "=" + properties.getProperty(key));
}
}

public static void printProp02(Properties properties) {
Set<Object> keys = properties.keySet();
for (Object key : keys) {
System.out.println(key.toString() + "=" + properties.get(key));
}
}

public static void printProp03(Properties properties) {
Set<Map.Entry<Object, Object>> entrySet = properties.entrySet();
for (Map.Entry<Object, Object> entry : entrySet) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}

public static void printProp04(Properties properties) {
Enumeration<?> e = properties.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = properties.getProperty(key);
System.out.println(key + "=" + value);
}
}
}

用户当前工作路径

System.getProperty("user.dir") : 用户当前工作路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Test {
public static void main(String[] args) throws IOException {

System.out.println(System.getProperty("os.name")); // Windows 10
System.out.println(System.getProperty("os.arch")); // amd64
System.out.println(System.getProperty("os.version")); // 10.0
System.out.println(System.getProperty("file.separator")); // \
System.out.println(System.getProperty("path.separator")); // ;
System.out.println(System.getProperty("line.separator")); // 换行符号(能看到换行效果)
System.out.println(System.getProperty("user.name")); // Administrator
System.out.println(System.getProperty("user.home")); // C:\Users\Administrator
System.out.println(System.getProperty("user.dir")); // E:\workspaces\idea\earth

File directory = new File("../moon");
try {

// 返回此抽象路径名的 '规范路径名' 字符串。'.'表示当前文件夹,'..'表示当前文件夹的上一级文件夹
System.out.println(directory.getCanonicalPath()); // 结果:E:\workspaces\idea\moon
// 返回此抽象路径名的 '绝对路径名' 字符串。不管'.'、'..',返回当前的路径加上在new File()时设定的路径
System.out.println(directory.getAbsolutePath()); // 结果:E:\workspaces\idea\earth\..\moon
// 返回此抽象路径名的 '字符串格式',即new File()时设定的路径
System.out.println(directory.getPath()); // 结果:..\moon
} catch (Exception e) {
}

}
}

classpath路径

Classpath - 维基百科

CLASSPATH - 百度百科

Java Classloader - 维基百科

classpath和jar - 廖雪峰

Classpath 是 .java 文件resource文件 编译 后的 输出目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static void main(String[] args) throws IOException {

// 获取当前类的路径(classpath根路径 + 包名)。如:/E:/earth/earth-demo/demo-a/target/classes/com/zhaolq/demo/a/
System.out.println("classpath current=" + Test.class.getResource("").getPath());

// 获取classpath根路径。如:/E:/earth/earth-demo/demo-a/target/classes/
System.out.println("classpath Root=" + Test.class.getResource("/").getPath());
System.out.println("classpath Root=" + Test.class.getClassLoader().getResource("").getPath());
System.out.println("classpath Root=" + ClassLoader.getSystemClassLoader().getResource("").getPath());
System.out.println("classpath Root=" + ClassLoader.getSystemResource("").getPath());
System.out.println("classpath Root=" + Thread.currentThread().getContextClassLoader().getResource("").getPath());

}
}

加载classpath下的资源文件

编译后输出到项目 classpath 路径下的所有文件都叫资源文件 (resource文件),和 resources 文件夹不同。

编译后的 .classs 文件也是资源文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Test {
public static void main(String[] args) throws IOException {

// 获取依赖模块或jar包下的资源文件
System.out.println("依赖模块resources文件夹下的资源路径=" + ClassLoader.getSystemClassLoader().getResource("log4j2.component.properties").getPath());
System.out.println("项目编译后的.class文件路径:" + ClassLoader.getSystemClassLoader().getResource("com/zhaolq/demo/a/Test.class").getPath());
System.out.println("依赖jar中的.class文件路径:" + ClassLoader.getSystemClassLoader().getResource("org/apache/commons/lang3/StringUtils.class").getPath());

// 加载配置文件,设置或更新键值,用做系统属性。
System.getProperties().load(ClassLoader.getSystemResourceAsStream("datasource.properties"));
System.getProperties().load(ClassLoader.getSystemClassLoader().getResourceAsStream("datasource.properties"));
// System.getProperties().load(Test.class.getResourceAsStream("datasource.properties")); // 这个方法报空指针
System.getProperties().load(Test.class.getClassLoader().getResourceAsStream("datasource.properties"));
System.getProperties().load(Test.class.getClassLoader().getSystemResourceAsStream("datasource.properties"));
System.getProperties().load(Thread.currentThread().getContextClassLoader().getResourceAsStream("datasource.properties"));
System.getProperties().load(Thread.currentThread().getContextClassLoader().getSystemResourceAsStream("datasource.properties")); // 这是个static方法
System.out.println(System.getProperty("db.url"));

// 加载配置文件,设置或更新键值,不用做系统属性
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("datasource.properties"));
System.out.println(properties.getProperty("db.url"));


/******************* 通过 URL 类的 openStream() 方法获取 InputStream *******************/
properties.load(Thread.currentThread().getContextClassLoader().getResource("datasource.properties").openStream());

}
}

加载与类同目录下的资源文件

1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
try {
String resourceFile = StringUtils.replace(new Object() {}.getClass().getPackage().getName(), ".", "/");
System.getProperties().load(Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceFile + "/demo.properties"));
} catch (IOException e) {
System.out.println("Properties file failed to load");
throw new RuntimeException(e);
}
}
}

classpath和classpath*区别

推荐:https://blog.51cto.com/u_15127669/4081246

classpath :只会从当前ClassLoader路径中查找文件,同名资源文件只会加载第一个。

classpath* :不仅在当前ClassLoader路径查找文件,还会在依赖jar中ClassLoader路径查找,查找顺序取决于jar包的加载顺序,同名资源文件都会加载,出现的相同属性前后哪个生效呢?

当项目中有多个classpath路径,并同时加载多个classpath路径下(此种情况多数不会遇到)的文件,*就发挥了作用,如果不加*,则表示仅仅加载第一个classpath路径。

通配符*

**/ 表示任意目录;**/applicationContext-*.xml 表示任意目录下的以 applicationContext- 开头的XML文件。