Создание объектов с Guava из файлов свойств - PullRequest
6 голосов
/ 21 ноября 2011

В наших приложениях мы очень часто используем файлы свойств. С нескольких месяцев я начал изучать гуаву, и мне это очень понравилось

Как лучше всего создать Map<String, Datasource>?

Формат файла свойств не является строгим. Его можно изменить, если лучше выразить его в другом формате?

Пример файла свойств:

datasource1.url=jdbc:mysql://192.168.11.46/db1
datasource1.password=password
datasource1.user=root
datasource2.url=jdbc:mysql://192.168.11.45/db2
datasource2.password=password
datasource2.user=root

Ответы [ 3 ]

6 голосов
/ 21 ноября 2011

Для этого проще всего использовать JSON, а не файл свойств:

{
  "datasources": [
    {
      "name": "datasource1",
      "url": "jdbc:mysql://192.168.11.46/db1",
      "user": "root",
      "password": "password"
    },
    {
      "name": "datasource2",
      "url": "jdbc:mysql://192.168.11.46/db2",
      "user": "root",
      "password": "password"
    }  
  ]
}

Тогда вы можете просто использовать библиотеку, такую ​​как Gson , чтобы преобразовать ее в объекты:

public class DataSources {
  private List<DataSourceInfo> dataSources;

  public Map<String, DataSource> getDataSources() {
    // create the map
  }
}

public class DataSourceInfo {
  private String name;
  private String url;
  private String user;
  private String password;

  // constructor, getters
}

Затем, чтобы получить карту:

Gson gson = new Gson();
Map<String, DataSource> dataSources = gson.fromJson(/* file or stream here */,
    DataSources.class).getDataSources();
5 голосов
/ 21 ноября 2011

Класс свойств является подклассом HashTable, который в свою очередь реализует Map.

Вы загружаете его как обычно с помощью:

Properties properties = new Properties();
    try {
        properties.load(new FileInputStream("filename.properties"));
    } catch (IOException e) { 
}

edit: Ok, поэтому вы хотите преобразовать его в Map;)

//First convert properties to Map<String, String>
Map<String, String> m = Maps.fromProperties(properties);

//Sort them so that password < url < user for each datasource and dataSource1.* < dataSource2.*. In your case default string ordering is ok so we can take a normal treemap
Map<String, String> sorted = Maps.newTreeMap();
sorted.putAll(m);

//Create Multimap<String, List<String>> mapping datasourcename->[password,url, user ]

    Function<Map.Entry<String, String>, String> propToList = new Function<String, Integer>() {
        @Override
        public String apply(Map.Entry<String, String> entry) {
            return entry.getKey().split("\\.")[0];
        }
    };

Multimap<Integer, String> nameToParamMap = Multimaps.index(m.entrySet(), propToList);

//Convert it to map
Map<String, Collection<String>> mm = nameToParamMap.asMap();

//Transform it to Map<String, Datasource>
Map<String, Datasource> mSD = Maps.transformEntries(mm, new EntryTransformer<String, Collection<String>, DataSource>() {
         public DataSource transformEntry(String key, Collection<String> value) {
            // Create your datasource. You know by now that Collection<String> is actually a list so you can assume elements are in order: [password, url, user]
            return new Datasource(.....)
         }
       };

//Copy transformed map so it's no longer a view
Map<String, Datasource> finalMap = Maps.newHashMap(mSD);

Возможно, есть более простой способ, но это должно сработать:)

Тем не менее вам лучше работать с json или xml.Вы также можете загружать свойства разных источников данных из разных файлов.

edit2: с меньшим количеством guava, с большим количеством java:

//Sort them so that password < url < user for each datasource and dataSource1.* < dataSource2.*. In your case default string ordering is ok so we can take a normal SortedSet
SortedSet <String> sorted = new SortedSet<String>();
sorted.putAll(m.keySet);

//Divide keys into lists of 3
Iterable<List<String>> keyLists = Iterables.partition(sorted.keySet(), 3);


Map<String, Datasource> m = new HashMap<String, Datasource>();
for (keyList : keyLists) {
    //Contains datasourcex.password, datasroucex.url, datasourcex.user
    String[] params = keyList.toArray(new String[keyList.size()]);
    String password = properties.get(params[0]);
    String url = properties.get(params[1]);
    String user = properties.get(params[2]);
    m.put(params[0].split("\\.")[0], new DataSource(....)
}
0 голосов
/ 21 ноября 2011

Если файл, который вы используете для настройки, не является строгим, вы можете использовать файл XML для хранения определения.

Пример определения:

<resources>
 <configuration>
   <datasrouce>
     <connection name="" url="" password="" user=""/>
     <connection name="" url="" password="" user=""/>
   </datasource>
 </configuration>
</resources>

Используя класс диспетчера подключений, вы можете просто прочитать XML, чтобы получить информацию о соединении и создать экземпляр соединений и управлять ими.

...