Java反射-替换YAML模板参数的值

一、背景

实践中我们有如下的YAML参数模板,我们想要替换YAML文件中的这几个参数值param1param22param3111以及param3122

param1: value1

param2:
  param21: value21
  param22: value22

param3:
  param31:
    param311:
      param3111: value3111
      param3112: value3112
    param312:
      param3121: value3121
      param3122: value3122

二、实施过程

2.1 转换YAML为Map

  1. 引入依赖:

      org.yaml
      snakeyaml
      1.21

  1. 转换YAML为Map
Yaml yaml = new Yaml();
Map map = yaml.load(valuesYaml);

2.2 定义模板参数对象

为了对模板中的参数值进行反射替换,我们需要将模板参数定义为对象,这里将模板中所有的value值作为字符串来处理,那么上述模板文件对应的对象:

# 1. 首先定义最外层的结构
@Data
public class Values {

    private String param1;
    private Param2Values param2;
    private Param3Values param3;
}

# 2. 然后定义Param2Values
@Data
public class Param2Values {

    private String param21;
    private String param22;
}

# 3. 然后定义Param3Values
@Data
public class MysqlHAPersistence {

    private Param31Values param31;
}

# 4. 然后定义Param31Values
@Data
public class Param31Values {

    private Param311Values param311;
    private Param312Values param312;
}

# 5. 然后定义Param311Values
@Data
public class Param311Values {

    private Param3111Values param3111;
    private Param3112Values param3112;
}

#### 类似的方式我们还需要定义好:Param312Values、Param3111Values、Param3112Values 、Param3121Values、Param3122Values 这四个对象

可以看出非常繁琐,而且一旦参数模板修改了,我们就需要修改代码

2.3 将2.1中生成的Map转换为对象存储

private Values convertValuesTemplateMap(Map map){
        String param1 = (String) map.get("param1");
        Map param2Map = (Map) map.get("param2");
        Param2Values param2 = new Param2Values();
        param2.setParam21(param2Map.get("param21"));
        param2.setParam22(param2Map.get("param22"));
      
        // 其他参数的转换过程类似
       
        Values values = new Values();
        values.setParam1(param1);
        values.setParam2(param2);
       
        return values;
    }

2.4 开始替换模板中的参数值

假设我们想要设置这几个值param1: new_value1, param22: new_value22, param3112: new_value3112

private Object copyProperties(Values obj, String key, String value){
            Object target = obj;
            Class clz = obj.class;
            
            // 我们通过小数点来标识模板文件中的层级关系,如:param3111表示为:param3.param31.param311.param3111
            String[] paramArgs = key.split("\\.");
            int i = 0;
            for (String fieldName : paramArgs){
                try {
                    PropertyDescriptor pd = new PropertyDescriptor(fieldName, clz);
                    if (i == chartParamArgs.length - 1){
                        // 找到了需要设置的参数,开始设置值
                        Method method = pd.getWriteMethod();
                        Field f = clz.getDeclaredField(fieldName);
                        method.invoke(target, value);
                    } else {
                        // 还没找到需要设置的参数,迭代更新clz和target参数
                        Field f = clz.getDeclaredField(fieldName);
                        i++;
                        clz = f.getType();
                        Method method = pd.getReadMethod();
                        target = method.invoke(target);
                    }
                } catch (Exception e){
                    log.error(String.format("get Field failed for fieldName: %s, ErrorMsg: %s", fieldName, e.getMessage()));
                }

            }  
            return obj;      
}

缺陷:和模板文件绑定死了,一旦模板文件修改,那么就需要改动代码,但是好在是能够实现参数值的替换

你可能感兴趣的:(Java反射-替换YAML模板参数的值)