1. 程式人生 > >Spring Boot 學習系列(07)—properties檔案讀取

Spring Boot 學習系列(07)—properties檔案讀取

此文已由作者易國強授權網易雲社群釋出。

歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。

傳統的properties讀取方式

  • 一般的,我們都可以自定義一個xxx.properties檔案,然後在工程的xml配置檔案中注入相關的配置bean,示例如下:

    <context:property-placeholder location="classpath:config/${spring.profiles.active:unknown}/zk.properties" order="1" ignore-unresolvable="true" ignore-resource-not-found="true"/><bean id="kafkaProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean" >
      <property name="ignoreResourceNotFound" value="true"/>
      <property name="location" value="classpath:config/${spring.profiles.active:unknown}/kafka.properties"/>
      <property name="fileEncoding" value="UTF-8" /></bean>
  • 然後就可以在我們需要使用的地方之間使用xxx.properties中配置的資訊。在Java和xml中使用示例分別如下:

    @Servicepublic class KafkaHotPostConsumer {@Value("#{kafkaProps['light.kafka.bootstrap.servers']}")
    private String KAFKA_BOOTSTRAP_SERVERS;
    <dubbo:registry id="faDataCenter" protocol="zookeeper" address="${zookeeper.servers}" group="${zookeeper.group.dataCenter}"/><bean id="kafkaClientL"
        class="com.netease.mq.kafka.KafkaProduerClient">
      <property name="level" value="low"></property>
      <property name="brokerList" value="#{kafkaProps['light.kafka.bootstrap.servers']}"></property></bean>
  • 當然我們也可以針對某一個特定的配置檔案,編寫操作的PropertiesUtil類來進行操作,在此不再展開。

Spring Boot的properties讀取方式

  • 在Spring Boot中對於配置檔案的讀取方式比較靈活,分別演示如下。

  • application.properties

    • 這個配置檔案是預設的核心配置檔案,原則上來說,如果有需要配置的資訊可以直接存放在這裡,不建議自定義配置檔案存放,這樣可以達到方便快速使用的目的。對於此配置檔案下的資訊讀取非常簡單,如果是在配置檔案中需要獲取已定義的資訊,則可直接使用,如下所示:

      #服務啟動埠server.port=7777#自定義欄位custom.url=http://localhost:${server.port}/query.do
    • 在Java程式碼中使用也非常簡單,可以通過@Value註解或者通過Environment類來獲取當前環境中載入的配置資訊,示例如下:

      @Value("${server.port}")private String port;@AutowiredEnvironment env;@GetMapping("/")public String hello(){
        System.out.println("my server port is =" + port);
        System.out.println("custom url = " + env.getProperty("custom.url","defaultValue"));  return "hello,world";
      }
  • 當然,如果我們需要自定義properties檔案來存取我們想要的資訊也是支援的。實際上,不論是application.properties還是自定義的demo.properties檔案,最終都會轉化對映一個具體的配置類,而我們實際上在程式碼中操作的就是這個配置類。下面我們演示下如何自定義配置檔案。

    • 新建配置檔案demo.properties,如下所示:

      demo.username=demo
      [email protected]
    • 然後編寫對應的對映類,如下所示,實際上,上面也有介紹,我們也可以使用@Value註解獲取配置資訊,不過用environment的方式獲取,可以指定預設值。這裡我們需要注意加入@Configuration的註解,然後指定對應的配置檔案路徑即可。

      import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;/**
      * 演示自定義配置檔案讀取
      * <p>
      * 
      * @date 2017/10/18 10:57.
      * @author bjyiguoqiang
      */@[email protected]("classpath:demo.properties")public class DemoProperties {  @Autowired
        Environment environment;  public String getUsername() {      return environment.getProperty("demo.username");
        }  public String getEmail() {      return environment.getProperty("demo.email");
        }
      }
    • 接下來我們就可以直接操作DemoProperties這個類來讀取配置資訊了。示例如下:

      @ResourceDemoProperties demoProperties;
      ....../**
      * 1、核心配置檔案的讀取示例
      * </p>
      * 2、自定義配置檔案的讀取示例
      * 
      * @return*/@GetMapping("/")public Object hello() {  //讀取自定義配置檔案
        String email = demoProperties.getEmail();
        String username = demoProperties.getUsername();
        logger.info("demo properties : email={},username={}", email, username);
      }
  • 當然我們也可以在啟動程式jar的時候指定外部的配置檔案,如果程式在啟動時就會優先載入外部的這個配置檔案,示例如下:

java -jar demo.jar --spring.config.location=/opt/config/application.properties

遇到的問題

  • 正常情況下,通過上面列舉的讀取方式基本能滿足我們的使用需求,但也存在特殊的情況。比如我們很多場景還是會引入第三方的jar包或需要自己封裝jar包來提供給其他服務使用,那麼這個時候不能強依賴spring boot框架的讀取方式。

  • 如果在我們的jar包需要獲取某一特定的配置檔案中的資訊該怎麼辦呢?這裡就需要注意了,不然就會掉進坑裡。這也是我們實際遇到的一個問題,原來在程式碼中讀取配置檔案程式碼示例如下:

BufferedInputStream in = null;
URL resourceFile = Thread.currentThread().getContextClassLoader().getResource("/demo.properties");String path = resourceFile.getPath();try {    in = new BufferedInputStream(new FileInputStream(path));
} catch (FileNotFoundException e) {   //.....}

PropertyResourceBundle resource = null;try {
    resource = new PropertyResourceBundle(in);
} catch (IOException e) {    //.....}
HashMap props = new HashMap();
Iterator uriArray = resource.keySet().iterator();String strTmp;while(uriArray.hasNext()) {
    strTmp = (String)uriArray.next();
    props.put(strTmp, resource.getObject(strTmp));
}String demoEmail  = (String)props.get("demo.email");
  • 上面的程式碼在非Spring Boot專案中執行是沒有什麼問題的,我們只需要在resources下存放demo.properties檔案即可正常讀取。但在spring boot專案中讀取卻會出現問題。丟擲的錯誤很直觀,就是提示在classpath下找不到對應的檔案。

  • 出現問題的根本原因在於Spring Boot 如果以jar包的形式進行部署,classpath路徑會被替換成jar:file:/xxx/xxx/classess!,最終生成的資源路徑為jar:file:/xxx/xxx/classess!/xx/xx.xx

  • 因為服務是通過jar包啟動的,通過系統的檔案系統並不能獲取到我們想要的檔案(比如demo.propeties),所有使用諸如new File(path)的形式就會出現問題

  • 我們可以變更以流的方式讀取來獲取jar中的類資原始檔。示例程式碼如下:

//直接返回StreamInputStream inputStream  = Thread.currentThread().getContextClassLoader().getResourceAsStream("demo.properties");
BufferedInputStream in  = new BufferedInputStream(inputStream);
PropertyResourceBundle resource = null;try {
    resource = new PropertyResourceBundle(in);
} catch (IOException e) {    //.....}
HashMap props = new HashMap();
Iterator uriArray = resource.keySet().iterator();String strTmp;while(uriArray.hasNext()) {
    strTmp = (String)uriArray.next();
    props.put(strTmp, resource.getObject(strTmp));
}String demoEmail  = (String)props.get("demo.email");

最後

  • 通過上面所述,結合大家親自實踐後,應該不難發現Spring Boot提供的配置檔案讀取更加的靈活強大,也符合框架本身快速開發的思想。

  • 不足之處,歡迎指正,謝謝~


免費體驗雲安全(易盾)內容安全、驗證碼等服務

更多網易技術、產品、運營經驗分享請點選


相關文章:
【推薦】 驗證碼示例程式碼演示——以php為例
【推薦】 分散式儲存系統可靠性系列二:系統估算示例