【建议收藏】读取*.properties文件数据的8种方法

6,591 阅读3分钟

前言

目前大多数的架构设计中都会采用外部化配置,因为从开发、测试、预发再到生产,不同的环境有不同的配置,不可能每次为了改配置而去改代码。所以外部化配置已经是一个不可或缺的设计。目前配置存储的文件类型也有yaml、properties等。今天我就来讲讲Java读取properties文件的数据的n种方法。

读取*.properties文件主要分两步:

  1. 找到资源路径
  2. 加载资源

根据找资源路径的不同方法以及加载资源数据的不同方法,将方法主要分为了以下8种:

一、基于ClassLoder的getResourceAsStream方法读取配置文件

二、基于getResourceAsStream()方法读取配置文件

三、基于ClassLoader类的getSystemResourceAsStream()静态方法读取配置文件

四、基于 FileInputStream 读取配置文件

五、基于ResourceBundle读取配置文件

六、基于PropertyResourceBundle读取配置文件

七、基于xml方式读取配置

八、基于注解读取配置

下面我进行一一讲解,首先我在resources下创建了一个config.properties,其中只包含一条配置就是name=crazyhzm。以下示例都是模拟读取该文件中的name属性。

一、基于ClassLoder的getResourceAsStream方法读取配置文件

本方法基于ClassLoder的getResourceAsStream方法,通过类加载器来定位资源,返回InputStream后用Properties对象进行加载。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream in = Test.class.getClassLoader().getResourceAsStream("config.properties");
        Properties properties = new Properties();
        properties.load(in);
        System.out.println(properties.getProperty("name"));
    }
}

二、基于getResourceAsStream()方法读取配置文件

这种方法是利用class的getResourceAsStream方法来定位资源文件,并且直接返回InputStream对象,然后通过Properties进行加载。

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream in = Test.class.getResourceAsStream("config.properties");
        Properties properties = new Properties();
        properties.load(in);
        System.out.println(properties.getProperty("name"));
    }
}

三、基于ClassLoader类的getSystemResourceAsStream()静态方法读取配置文件

该方法使用ClassLoader的getSystemResourceAsStream()静态方法来定位资源,并且返回InputStream,最后用Properties来加载。其实上一种方法的getResourceAsStream中也调用了ClassLoader.getSystemResourceAsStream,我们来看看源码:

 public InputStream getResourceAsStream(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        // A system class.
        return ClassLoader.getSystemResourceAsStream(name);
    }
    return cl.getResourceAsStream(name);
}

该方法示例:

public class Test {
    public static void main(String[] args) throws IOException {
        InputStream in = ClassLoader.getSystemResourceAsStream("config.properties");
        Properties properties = new Properties();
        properties.load(in);
        System.out.println(properties.getProperty("name"));
    }
}

四、基于 FileInputStream 读取配置文件

这种方法通过类的路径来定位properties文件资源的路径,然后通过FileInputStream读取流,最后通过java.util.Properties类的load()方法来加载数据。

public class Test {
    public static void main(String[] args) throws IOException {
        URL url = Test.class.getClassLoader().getResource("config.properties");
        if (url != null) {
            String fileName = url.getFile();
            InputStream in = new BufferedInputStream(new FileInputStream(fileName));
            Properties properties = new Properties();
            properties.load(in);
            System.out.println(properties.getProperty("name"));
        }
    }
}

五、基于ResourceBundle读取配置文件

ResourceBundle其实是用来解决国际化和本地化问题的,但是需要在多种语言中切换,必然会有一个配置文件来指定切换的内容,比如需要把click转化为点击。那需要在配置文件中将这两个值进行对应,具体的我就不再这里赘述,跟本文关系不大,在读取配置文件时候,利用ResourceBundle来读取properties文件也不乏是一种方案。

下面为了使用ResourceBundle,我新增了一个配置文件,名叫config_en_US.properties,内容和config.properties一样,你会发现创建完后,Resource文件夹名字有点变化了。。

下面是使用示例:

public class Test {
    public static void main(String[] args) throws IOException {
        Locale locale1 = new Locale("en", "US");
        ResourceBundle resourceBundle = ResourceBundle.getBundle("config", locale1);
        System.out.println(resourceBundle.getString("name"));

    }
}

六、基于PropertyResourceBundle读取配置文件

PropertyResourceBundle是ResourceBundle的子类,同样我们也可以利用PropertyResourceBundle来加载配置文件的数据,具体的示例如下:

public class Test {
    public static void main(String[] args) throws IOException {
        URL url = Test.class.getClassLoader().getResource("config.properties");
        if (url != null) {
            InputStream in = new BufferedInputStream(new FileInputStream(url.getFile()));
            ResourceBundle resourceBundle = new PropertyResourceBundle(in);
            System.out.println(resourceBundle.getString("name"));
        }
    }
}

七、基于xml方式读取配置

  1. 加入依赖spring-context:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
  1. 创建UserService
@Service
public class UserService {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 创建application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:config.properties"/>

    <bean id="userService" class="UserService">
        <property name="name" value="${name}"/>
    </bean>
</beans>
  1. 编写测试类
@Service
public class Test {
    @Resource
    private UserService userService;

    @PostConstruct
    public void getName(){
        System.out.println(userService.getName());
    }
}

这种方式必须通过Spring来加载bean,才能够注入属性值,这边写的@PostConstruct只是为了用来测试,启动前需要搭建一个启动类。这种方式需要注意的是被注入的属性必须实现setter方法,比如setName。

八、基于注解读取配置

还是上述方法的例子,这次的xml只需要加载properties,而自动注入则由@Value注解来完成。

  1. 引入依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>
  1. 编写application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:config.properties"/>

</beans>
  1. 编写UserService
public class UserService {
    @Value("${name}")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

送福利区域