如何在 java 中的 config.properties 文件的特定对之间创建关系?

How to create a relationship between specific pairs of a config.properties file in java?

我有多个外部 JAR 文件,其中包括我的应用程序的特殊程序。应用程序本身此时只需要一个程序,具体取决于用户输入的程序名称。

话虽如此,我已经创建了一个 config.properties 文件,其中包含有关每个程序的相关信息。

config.properties

PROC.1=NameOfProc
IMPL.1=path.to.main.class.of.jar
LIB.1=lib/somejar.jar

PROC.2=NameOfProc
IMPL.2=path.to.main.class.of.jar
LIB.2=lib/somejar.jar

...

我已经能够读取 config.properties 文件,但我无法在属于同一对的文件对之间创建关系。

java代码

try {
    Properties prop = new Properties();
    prop.load(new FileInputStream("path/to/config.properties"));
    String proc = properties.getProperty("PROC.1");
    String impl = properties.getProperty("IMPL.1");
    String lib = properties.getProperty("LIB.1");
} catch (Exception e) {

}

我现在想知道如何在这些对之间建立关系,这样我就可以仅通过 PROC.X 名称来接收 IMPL.X 值和 LIB.X 值。

有人知道我怎样才能做到这一点吗?我非常感谢任何形式的帮助,sheers!

您应该可以使用 Jackson 库 HERE

做到这一点(只需稍微更改您的属性文件结构)

文件格式必须遵循常用的约定,以句点(“.”)作为逻辑路径分隔符。

示例:

proceedings[1].name = NameOfProc
proceedings[1].implementation = path.to.main.class.of.jar
proceedings[1].libraryPath  = lib/somejar.jar

proceedings[2].name = NameOfProc2
proceedings[2].implementation = path2.to.main.class.of.jar
proceedings[2].libraryPath  = lib/somejar2.jar

完成后 - 您现在应该能够将其绑定到以下结构:

public class Configuration {
   public List<Proceeding> proceedings;
}

public class Proceeding {
    String name;
    String implementation;
    String libraryPath;
}

使用这样的东西:

JavaPropsMapper mapper = new JavaPropsMapper();

Configuration cfg = mapper.readValue(new File("path_to_your.properties"),
   Configuration.class);

您可以将其转换为嵌套地图。

public static void main(String[] args) {
    Properties prop = new Properties();
    prop.setProperty("PROC.1", "procOne");
    prop.setProperty("IMPL.1", "implOne");
    prop.setProperty("LIB.1", "libOne");
    prop.setProperty("PROC.2", "procTwo");
    prop.setProperty("IMPL.2", "implTwo");
    prop.setProperty("LIB.2", "libTwo");
    System.out.println("prop=" + prop);

    Map<String, Map<String, String>> mappedProp = prop.entrySet().stream()
        .map(e -> Map.entry(e.getKey().toString(), e.getValue().toString()))
        .collect(Collectors.groupingBy(
            e -> e.getKey().replaceFirst("\..*$", ""),
            Collectors.mapping(Function.identity(),
                Collectors.toMap(e -> e.getKey().replaceFirst("^.*\.", ""),
                    Map.Entry::getValue))));

    System.out.println("mappedProp=" + mappedProp);
    System.out.println("PROC=" + mappedProp.get("PROC"));
    System.out.println("PROC.1=" + mappedProp.get("PROC").get("1"));
}

输出:

prop={IMPL.2=implTwo, PROC.1=procOne, PROC.2=procTwo, IMPL.1=implOne, LIB.2=libTwo, LIB.1=libOne}
mappedProp={IMPL={1=implOne, 2=implTwo}, PROC={1=procOne, 2=procTwo}, LIB={1=libOne, 2=libTwo}}
PROC={1=procOne, 2=procTwo}
PROC.1=procOne

或者,您可以使用简单的循环来完成。

Map<String, Map<String, String>> mappedProp = new LinkedHashMap<>();
for (Map.Entry<Object, Object> e : prop.entrySet()) {
    String key = e.getKey().toString();
    String key1 = key.replaceFirst("\..*$", "");
    String key2 = key.replaceFirst("^.*\.", "");
    String value = e.getValue().toString();
    mappedProp.computeIfAbsent(key1, k -> new LinkedHashMap<>()).put(key2, value);
}

将属性的 keySet 与 RegEx 模式匹配,如本例所示,其中有趣的键的收集是在方法 grepPropertyKey() 中完成的

public class PropertySample {

Properties properties = new Properties();


public static void main(String[] args) {
    
    PropertySample me = new PropertySample();
    me.run();
    
}


protected void run() {

    // Setup some properties
    properties.put("PROC.1", "NameOfProc");
    properties.put("IMPL.1", "path.to.main.class.of.jar");
    properties.put("LIB.1", "lib/somejar.jar");

    properties.put("PROC.2", "NameOfOtherProc");
    properties.put("IMPL.2", "path.to.main.someOtherClass.of.jar");
    properties.put("LIB.2", "lib/someOtherjar.jar");
    
    for(int index = 1; index <=2; index++) {
    
        /* get list of keys filtered by the RegEx:
         *   a: From begin of the string consume all characters NOT matching a literal dot
         *   b: consume one literal dot
         *   c: MATCH the literal number given by index
         *   d: match anything else up to end of string
         */
        String regEx = "^[^\.]+\." + Integer.toString(index) + ".*";
        
        List<String> keyList = grepPropertyKey(regEx);
        
        for(String key: keyList) {
            System.out.println(
                "index: " + index 
              + " key: " + key
              + "\t value: " + properties.get(key)
            );
            
        }
        
        System.out.println();
        
    } // index
            
} // main()


protected List<String> grepPropertyKey(final String aPattern) {
    
    // prepare result set
    List<String> result = new ArrayList<String>();
    
    // get the key set from properties
    for(Object key : properties.keySet()) {
        
        // and match each key against the filter given in aPatern 
        if(((String)key).matches(aPattern)) {
            
            // add match to result
            result.add((String)key);
            
        } // fi
        
    } // rof
    
    return result;
    
} // grepPropertyKey()

}

输出为

index: 1 key: LIB.1      value: lib/somejar.jar
index: 1 key: PROC.1     value: NameOfProc
index: 1 key: IMPL.1     value: path.to.main.class.of.jar

index: 2 key: LIB.2      value: lib/someOtherjar.jar
index: 2 key: PROC.2     value: NameOfOtherProc
index: 2 key: IMPL.2     value: path.to.main.someOtherClass.of.jar