一.应用场景
    使用Spring Boot开发,经常需要自定义配置属性,例如系统全局属性,或者外部调用的常量属性等,那么这些配置属性应该放在哪里比较合适?怎么读取并在代码中使用呢?

二. 属性配置
    在Spring Boot中,有两种常用的配置文件格式:properties和yml。下面总结了几种常见的属性配置和读取方式:

  1. 直接使用JDK自带的 java.util.ResourceBundle
    JDK本身提供了 java.util.ResourceBundle 工具类可以用于读取properties配置文件。
package com.hong.util;

import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * @author wanghong
 * @date 2019/06/14 22:48
 * properties属性文件读取器
 **/
public class PropertiesReader {

    private ResourceBundle resourceBundle;

    public PropertiesReader(String propertiesHolder) {
        this.resourceBundle = ResourceBundle.getBundle(propertiesHolder, Locale.getDefault());
    }

    public String getLabel(String key) {
        String label;
        try {
            label = new String(resourceBundle.getString(key).getBytes("ISO-8859-1"), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return label;
    }
}
package com.hong.config;

import com.hong.util.PropertiesReader;

/**
 * @author wanghong
 * @date 2019/06/14 22:49
 * App端属性配置常量类,绑定到类路径下app_config.properties资源
 **/
public class AppConfig {
    private static PropertiesReader getPropertiesVal = new PropertiesReader("app_config");

    public static final String MY_PROP = getPropertiesVal.getLabel("myProp");
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class ConfigTest {
   @Test
   public void testConfig(){
       System.out.println(AppConfig.MY_PROP); //123456
   }
}
  1. @ConfigurationProperties
package com.hong.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author wanghong
 * @date 2019/06/14 23:08
 **/
@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig2 {
   private String version;
}
package com.hong.controller;

import com.hong.config.AppConfig2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wanghong
 * @date 2019/06/14 23:14
 **/
@Api(value = "测试控制器")
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private AppConfig2 appConfig2;

    @ApiOperation(value = "属性读取测试")
    @RequestMapping(value = "testConfig",method = RequestMethod.GET)
    public String testConfig() {
        String version = appConfig2.getVersion();
        return version;
    }
}

springboot 识别公式 springboot工具类获取配置属性_java

如果现在 application-dev.yml中也定义了该属性:

springboot 识别公式 springboot工具类获取配置属性_spring_02


且 spring.profiles.active=dev,那么读取到的 version = 1.0.0

  1. @PropertySource
    现在再来看另一种场景: 假如我在 app_config.properties中也定义了该属性:

    如何让 AppConfig2中读取的值是该文件中配置的值呢?这时就要手动指定属性源了。
package com.hong.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * @author wanghong
 * @date 2019/06/14 23:08
 **/
@Data
@Component
@PropertySource(value = { "classpath:app_config.properties" }, encoding = "UTF-8")
@ConfigurationProperties(prefix = "app")
public class AppConfig2 {
   private String version;
}

但这里有一个坑,我本机Spring Boot使用的版本是2.0.4.RELEASE,如果在Spring Boot默认的全局属性文件application.yml或application.properties或application-{profile}.yml或application-{profile}.properties中存在与自定义属性配置文件中同名的属性,那么即使加了@PropertySource(value = { “classpath:app_config.properties” }, encoding = “UTF-8”)也不管用,最终读取到的还是默认全局属性文件中的值,当然一般出现这种情况,就是命名冲突的问题了,注意下就行了。

还有一种场景即使同一个属性值在不同的profile环境中值是不同的,如app_config.properties在dev环境下是1.1.0,在prod下是1.2.0,这时我们可以在resources目录下分别创建dev和prod两个文件夹,放置app_config.properties,然后设置下 @PropertySource的文件路径。

springboot 识别公式 springboot工具类获取配置属性_spring_03


springboot 识别公式 springboot工具类获取配置属性_spring_04


当然这种情况就是需要做到环境隔离了,如果是微服务的话,可以结合Spring Cloud使用分布式配置中心服务,将不同环境的配置放到git中方便修改和统一管理。

  1. @Value
package com.hong.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * @author wanghong
 * @date 2019/06/15 0:36
 **/
@Data
@Component
@PropertySource("classpath:app_config.properties")
public class AppConfig3 {
    @Value("${app.version}")
    private String version;
}
  1. @ConfigurationProperties与@Value的区别