java如何实时动态获取properties文件的内容

 更新时间:2021年09月14日 12:01:09   作者:小元子子  
这篇文章主要介绍了java如何实时动态获取properties文件的内容,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

实时动态获取properties文件的内容

用“ClassLoader.getResourceAsStream”读取properties文件时会发现修改了.properties后,即使重新执行,读入的仍为修改前的参数。

此问题的原因在于ClassLoader.getResourceAsStream读入后,会将.properties保存在缓存中,重新执行时会从缓存中读取,而不是再次读取.properties文件。

动态读取的代码

import java.util.Properties; 
/**
 * 实时动态获取properties文件的值
 * @author Administrator
 *
 */
public class demo01 {
 /**
  * 根据配置变量实时获取配置文件中的值
  * @param key 配置名
  * @param filePath 配置文件路径名,例如:test.properties
  * @return 配置值
  */
 public static String getCurrentPropertiesValue(String key,String filePath){
  String value="";
  Properties p = new Properties();
  try {
   //非实时动态获取
   //p.load(new InputStreamReader(this.class.getClassLoader().getResourceAsStream(filePath), "UTF-8"));
   //下面为动态获取
   String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
   InputStream is = new FileInputStream(path +File.separator+ filePath);
   p.load(is);
   value=p.getProperty(key);
  } catch (UnsupportedEncodingException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return value;
 }
}

读取配置文件 Properties VS ResourceBundle

在java开发中, 对于一些常用的配置性的信息, 通常会采用存放在属性文件中, 因为修改配置文件无须重新编译jar包. 对于属性文件,通常可以使用Properties和ResourceBundle 两个类来解析. 需要注意的是, 默认情况下java工程中的*.properties文件编码格式是ISO-8859-1, Properties和ResourceBundle也是按照ISO-8859-1格式来解析属性文件中字符串的. 所以对于解析包含中文的熟悉文件时,需要额外注意.

  • ResourceBundle: 通常用于解析国际化资源属性文件, 会根据本地环境自动选择对应的国际化资源.
  • Properties: 用来解析普通属性文件

1. 常用API

1.1 Properties 常用API

Properties 继承Hashtable<Object,Object>类.

方法签名 方法描述
public String getProperty(String key 获取属性文件中的Key, 如果key不存在返回Null
public String getProperty(String key, String defaultValue) 获取属性文件中key对象的value, 如果key不存在则返回默认值defaultValue
public Object get(String key) 父类HashTable中的方法, 返回值类型为Object

1.2 ResourceBundle 常用API

ResourceBundle 是一个接口, 默认使用PropertyResourceBundle来解析属性文件.

方法签名 方法描述
public Locale getLocale() 获取本地国际化环境
public Enumeration getKeys() 获取属性文件中所有key
public final String getString(String key) 获取属性文件中key对应的value, 返回值为String, 如果不存在, 则抛出异常
public final Object getObject(String key) 获取属性文件中key对应的value, 返回值为Object, 如果不存在, 则抛出异常

2. Properties 解析属性文件

默认使用ISO-8859-1 解析配置文件中的字符串, 所以会导致中文乱码.

2.1 解析纯英文配置文件

// 默认编码(ISO-8859-1)读取属性文件, 中文乱码
@Test
public void test_properties_en() throws IOException{
 
 // 属性文件位置, 相对路径为src/main/resources 或 src/test/resources, 不能添加classpath:/前缀
 String propertyFileName = "jdbc.properties";
 
 // 获取字节流
 InputStream is = getClass().getClassLoader().getResourceAsStream(propertyFileName);
 
 // 创建属性文件, 并加载文件内容
 Properties properties = new Properties();
 properties.load(is); 
 String username = properties.getProperty("jdbc.username");
 String password = properties.getProperty("jdbc.password");
 System.out.println("username:" + username + ", password:" + password); 
}

2.2 解析含中文配置文件

默认使用ISO-8859-1, 采用InputStreamReader转换为UTF8字符流.

// 指定读取文件编码方式,支持读取中文
@Test
public void test_properties_zh() throws IOException{
 
 // 属性文件位置, 相对路径为src/main/resources 或 src/test/resources, 不能添加classpath:/前缀
 String propertyFileName = "jdbc.properties";
 
 // 获取字节流
 InputStream is = getClass().getClassLoader().getResourceAsStream(propertyFileName);
 
 // 转换为UTF-8格式字符流
 InputStreamReader isr = new InputStreamReader(is, "UTF-8");
 
 // 创建属性文件, 并加载文件内容
 Properties properties = new Properties();
 properties.load(isr); 
 String username = properties.getProperty("jdbc.username");
 String password = properties.getProperty("jdbc.password");
 System.out.println("username:" + username + ", password:" + password); 
}

3. ResourceBundle 解析属性文件

3.1 解析纯英文配置文件

@Test
public void testRb_en() {
 // 资源配置文件,无须写文件后缀名, 默认寻找properties文件
 String bundleName = "jdbc";
 
 // 设置本地默认环境为英文环境
 Locale.setDefault(Locale.ENGLISH);
 
 // 指定加载
 ResourceBundle rb = ResourceBundle.getBundle(bundleName);
 
 String username = rb.getString("jdbc.username");
 String password = rb.getString("jdbc.password");
 System.out.println("username:" + username + ", password:" + password);
}

3.2 解析含中文配置文件

// 处理中文
@Test
public void testRb_zh() {
 // 资源配置文件,无须写文件后缀名, 默认寻找properties文件
 String bundleName = "jdbc";
 
 // 根据本地默认环境加载资源配置文件
 ResourceBundle rb = ResourceBundle.getBundle(bundleName); 
 String username = iso2Utf8(rb.getString("jdbc.username"));
 String password = iso2Utf8(rb.getString("jdbc.password"));
 System.out.println("username:" + username + ", password:" + password); 
}
/**
 * @Description iso编码格式字符串转换为UTF8格式
 * @param str iso 编码字符串
 * @return
 * @author zongf
 * @date 2019年1月8日-下午3:55:29
 */
private String iso2Utf8(String str) {
 if(null == str) return null;
 
 try {
  return new String(str.getBytes("ISO-8859-1"), "UTF-8");
 } catch (UnsupportedEncodingException e) {
  e.printStackTrace();
 }
 return null;
}

4. 属性文件

笔者创建的是maven 工程, 使用的是junit 单元测试, 所以笔者的配置文件存放在 src/test/resources 目录下.

jdbc.properties

jdbc.username=张三
jdbc.password=123456

jdbc_zh.properties

jdbc.username=张三
jdbc.password=123456

jdbc_en.properties

jdbc.username=zhangsan
jdbc.password=123456

5. 实战推荐

笔者认为, 一个设计良好的属性配置类应该是一个常量类, 至少需要符合两个设计原则:

属性一旦设置不可动态修改, 即使在编译环境也不能调用修改方法.

能够直接通过类属性进行访问, 无须通过类对象访问

自动装配属性, 而无须手动解析熟悉文件(spring中可借助自带注解或自定义注解实现)

public class JdbcProperty { 
 /** 用户名 */
 public static final String username;
 
 /** 用户密码 */
 public static final String password;
 
 // 在Spring应用中,可借助注解或自定义注解进行自动装配,笔者此处只针对一般java应用
 static {
  
  // 加载属性文件
  ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
  
  // 初始化属性
  username = resourceBundle.getString("jdbc.username");
  password = resourceBundle.getString("jdbc.password");  
 }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java获取指定父节点、子节点的方法实现

    Java获取指定父节点、子节点的方法实现

    在Java中,要获取指定节点的父节点和子节点,通常需要使用 DOM,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • POI读取excel简介_动力节点Java学院整理

    POI读取excel简介_动力节点Java学院整理

    这篇文章主要介绍了POI读取excel简介,详细的介绍了什么是Apache POI和组件,有兴趣的可以了解了解一下
    2017-08-08
  • Java自定义过滤器和拦截器实现ThreadLocal线程封闭

    Java自定义过滤器和拦截器实现ThreadLocal线程封闭

    本文主要介绍了Java自定义过滤器和拦截器实现ThreadLocal线程封闭,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Java中常见的陷阱题及答案

    Java中常见的陷阱题及答案

    在电脑里找到一份当时学习JAVA时的笔记,看到一些现在已经遗忘的细节。稍微整理了几个,发出来与大家分享。这篇文章主要介绍了Java中常见的陷阱题及答案,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • SpringMVC之RequestContextHolder详细解析

    SpringMVC之RequestContextHolder详细解析

    这篇文章主要介绍了SpringMVC之RequestContextHolder详细解析,正常来说在service层是没有request的,然而直接从controlller传过来的话解决方法太粗暴,后来发现了SpringMVC提供的RequestContextHolder,需要的朋友可以参考下
    2023-11-11
  • Java实现一个简易聊天室流程

    Java实现一个简易聊天室流程

    这篇文章主要介绍了我的java课程设计一个多人聊天室(socket+多线程)本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • 如何解决SpringBoot2.6及之后版本取消了循环依赖的支持问题

    如何解决SpringBoot2.6及之后版本取消了循环依赖的支持问题

    循环依赖指的是两个或者多个bean之间相互依赖,形成一个闭环,SpringBoot从2.6.0开始默认不允许出现Bean循环引用,解决方案包括在全局配置文件设置允许循环引用存在、在SpringApplicationBuilder添加设置允许循环引用、构造器注入
    2024-10-10
  • Kryo框架使用方法代码示例

    Kryo框架使用方法代码示例

    这篇文章主要介绍了Kryo框架的相关内容,文中向大家分享了Kryo框架使用方法代码示例,小编觉得挺不错的,希望能给大家一个参考。
    2017-10-10
  • Spring Boot实现STOMP协议的WebSocket的方法步骤

    Spring Boot实现STOMP协议的WebSocket的方法步骤

    这篇文章主要介绍了Spring Boot实现STOMP协议的WebSocket的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • SpringBoot实现图片识别文字的四种方式小结

    SpringBoot实现图片识别文字的四种方式小结

    本文主要介绍了SpringBoot实现图片识别文字的四种方式,包括Tess4J,百度智能云,阿里云,腾讯云这四种,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02

最新评论