目前大多数的架构设计中都会采用外部化配置,由于从开发、测试、预发再到生产,不一样的环境有不一样的配置,不可能每次为了改配置而去改代码。因此外部化配置已是一个不可或缺的设计。目前配置存储的文件类型也有yaml、properties等。今天我就来说讲Java读取properties文件的数据的n种方法。java
读取*.properties文件主要分两步:spring
根据找资源路径的不一样方法以及加载资源数据的不一样方法,将方法主要分为了如下8种:markdown
1、基于ClassLoder的getResourceAsStream方法读取配置文件架构
2、基于getResourceAsStream()方法读取配置文件app
3、基于ClassLoader类的getSystemResourceAsStream()静态方法读取配置文件测试
4、基于 FileInputStream 读取配置文件this
5、基于ResourceBundle读取配置文件url
6、基于PropertyResourceBundle读取配置文件spa
7、基于xml方式读取配置架构设计
8、基于注解读取配置
下面我进行一一讲解,首先我在resources下建立了一个config.properties,其中只包含一条配置就是name=crazyhzm。如下示例都是模拟读取该文件中的name属性。
本方法基于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")); } } 复制代码
这种方法是利用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()静态方法来定位资源,而且返回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")); } } 复制代码
这种方法经过类的路径来定位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实际上是用来解决国际化和本地化问题的,可是须要在多种语言中切换,必然会有一个配置文件来指定切换的内容,好比须要把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是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")); } } } 复制代码
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.10.RELEASE</version> </dependency> 复制代码
@Service public class UserService { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 复制代码
<?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> 复制代码
@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注解来完成。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.10.RELEASE</version> </dependency> 复制代码
<?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> 复制代码
public class UserService { @Value("${name}") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 复制代码