zoukankan      html  css  js  c++  java
  • 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
        demo.email=demo@163.com
      • 然后编写对应的映射类,如下所示,实际上,上面也有介绍,我们也可以使用@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
        */@Configuration@PropertySource("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为例
    【推荐】 分布式存储系统可靠性系列二:系统估算示例

  • 相关阅读:
    Mybatis的分页查询
    Mybatis的动态标签
    mybatis include标签
    mybatis 的<![CDATA[ ]]>
    Mybatis 示例之 SelectKey(转)
    mybatis foreach标签
    加密解密
    Sensor传感器(摇一摇)
    二维码的生成和扫描
    Camera摄像头
  • 原文地址:https://www.cnblogs.com/zyfd/p/9884676.html
Copyright © 2011-2022 走看看