欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Spring Boot 自定义PropertySourceLoader

程序员文章站 2024-03-31 12:42:04
springboot 的配置文件内置支持 properties、xml、yml、yaml 几种格式,其中 properties和xml 对应的loader类为 proper...

springboot 的配置文件内置支持 properties、xml、yml、yaml 几种格式,其中 properties和xml 对应的loader类为 propertiespropertysourceloader ,yml和yaml 对应的loader类为 yamlpropertysourceloader。

观察这2个类可以发现,都实现自接口 propertysourceloader 。所以我们要新增支持别的格式的配置文件,就可以通过实现接口 propertysourceloader 来实现了。

下面实现了一个 json 格式的配置文件 loader类:

package com.shanhy.sboot.property;

import java.io.ioexception;
import java.io.inputstream;
import java.util.hashmap;
import java.util.linkedlist;
import java.util.list;
import java.util.map;

import org.springframework.boot.env.propertysourceloader;
import org.springframework.boot.json.jsonparser;
import org.springframework.boot.json.jsonparserfactory;
import org.springframework.core.env.mappropertysource;
import org.springframework.core.env.propertysource;
import org.springframework.core.io.resource;

/**
 * json格式配置文件加载器
 * 
 * @author 单红宇(csdn catoop)
 * @create 2017年4月20日
 */
public class jsonpropertysourceloader implements propertysourceloader {

  public string[] getfileextensions() {
    // 配置文件格式(扩展名)
    return new string[] { "json" };
  }

  public propertysource<?> load(string name, resource resource, string profile) throws ioexception {
    // 处理机制参考propertiespropertysourceloader
    // 无论profile有没有值,底层都会尝试先执行 load(string name, resource resource, null),所以这个地方之间判断等于null即可。
    // 当前版本springboot-1.5.2(后续版本未知)详见 configfileapplicationlistener 的 445 行
    if (profile == null) {
      map<string, object> result = mappropertysource(resource);
      return new mappropertysource(name, result);
    }
    return null;
  }

  /**
   * 解析resource为map
   *
   * @param resource
   * @return
   * @throws ioexception
   * 
   * @author 单红宇(csdn catoop)
   * @create 2017年4月20日
   */
  private map<string, object> mappropertysource(resource resource) throws ioexception {
    if (resource == null) {
      return null;
    }
    map<string, object> result = new hashmap<string, object>();
    jsonparser parser = jsonparserfactory.getjsonparser();
    map<string, object> map = parser.parsemap(readfile(resource));
    nestmap("", result, map);
    return result;
  }

  /**
   * 读取resource文件内容为字符串
   *
   * @param resource
   * @return
   * @throws ioexception
   * 
   * @author 单红宇(csdn catoop)
   * @create 2017年4月20日
   */
  private string readfile(resource resource) throws ioexception {
    inputstream inputstream = resource.getinputstream();
    list<byte> bytelist = new linkedlist<byte>();
    byte[] readbyte = new byte[1024];
    int length;
    while ((length = inputstream.read(readbyte)) > 0) {
      for (int i = 0; i < length; i++) {
        bytelist.add(readbyte[i]);
      }
    }
    byte[] allbytes = new byte[bytelist.size()];
    int index = 0;
    for (byte solobyte : bytelist) {
      allbytes[index] = solobyte;
      index += 1;
    }
    return new string(allbytes, "utf-8");
  }

  /**
   * 处理map(map中可能还嵌套map,递归处理),最终输出一个非嵌套的map
   *
   * @param prefix
   *      前缀
   * @param result
   *      处理后的map
   * @param map
   *      处理前的map
   * 
   * @author 单红宇(csdn catoop)
   * @create 2017年4月20日
   */
  @suppresswarnings("unchecked")
  private void nestmap(string prefix, map<string, object> result, map<string, object> map) {
    if (prefix.length() > 0) {
      prefix += ".";
    }
    for (map.entry<string, object> entryset : map.entryset()) {
      if (entryset.getvalue() instanceof map) {
        nestmap(prefix + entryset.getkey(), result, (map<string, object>) entryset.getvalue());
      } else {
        result.put(prefix + entryset.getkey().tostring(), entryset.getvalue());
      }
    }
  }
}

然后在 src/main/resources 中创建 meta-inf/spring.factories 文件,内容为:

org.springframework.boot.env.propertysourceloader=\
com.shanhy.sboot.property.jsonpropertysourceloader

创建测试的配置文件 application.json

{
  "custom": {
    "property": {
      "message": "测试数据"
    }
  }
}

创建验证结果的 hellocontroller.java

@restcontroller
public class hellocontroller {

  @value("${custom.property.message:}")
  private string customproperty;

  @requestmapping("/test")
  public string test() {
    return customproperty;
  }
}

启动工程服务,浏览器访问 http://localhost:8080/test 即可查看输出的结果为 “测试数据”;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。