Библиотека чтения / записи безопасной конфигурации для Java?

#java #configuration

#java #конфигурация

Вопрос:

Существует ли хорошая библиотека конфигурации для Java, которая позволит мне читать настройки типобезопасным способом? Например, взяв мой созданный интерфейс IConfiguration с объявленными параметрами получения и установки и позволив мне читать / записывать конфигурацию через него.

Немного скучно читать настройки с помощью properties.getProperty("group.setting") , а затем приводить их к нужному типу. Конфигурация Apache commons позволяет использовать что-то вроде config.getDouble("number") , но «число» здесь снова является строкой, и я хотел бы иметь возможность делать что-то вроде double value = config.GetNumber() .

Ответ №1:

Библиотека ВЛАДЕЛЬЦА делает то, что вы хотите.

Ответ №2:

Я думаю, что библиотека конфигурации typesafe — это то, что вам может понадобиться. Вот ссылка

Это типобезопасная библиотека. Вот пример того, как использовать эту библиотеку:

 import com.typesafe.config.ConfigFactory

Config conf = ConfigFactory.load();
int bar1 = conf.getInt("foo.bar");
Config foo = conf.getConfig("foo");
int bar2 = foo.getInt("bar");
  

Основная причина, по которой я рекомендую эту библиотеку, заключается в том, что она может читать файлы HOCON. Это расшифровывается как «Оптимизированная для человека нотация объектов конфигурации» и является надмножеством JSON:

 {
    "foo" : {
        "bar" : 10,
        "baz" : 12
    }
}
  

В ней есть много функций, которые делают ее более читаемой. Например, пропуск специальных символов ( , , : , {} ). И самая крутая вещь — это наследование:

 standard-timeout = 10ms
foo.timeout = ${standard-timeout}
bar.timeout = ${standard-timeout}
  

И если вы дублируете поле со значением объекта, то объекты объединяются с помощью last-one-wins. Итак:

 foo = { a : 42, c : 5 }
foo = { b : 43, c : 6 }
  

означает то же самое, что:

 foo = { a : 42, b : 43, c : 6 } 
  

Пожалуйста, загляните в файл readme проекта, чтобы узнать больше об этой замечательной библиотеке конфигурацииhttps://github.com/typesafehub/config

Ответ №3:

Вы можете определить файл конфигурации XML с помощью XSD, а затем сгенерировать исходный код JAXB с помощью XJC. Каждый тип XSD сопоставляется классу Java, который вы можете легко маршалировать / отменять маршалирование

Пример. XSD:

 <xsd:simpleType name="GroupType">
  <xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1"/>
    <xsd:maxInclusive value="255"/>
  </xsd:restriction>
</xsd:simpleType>
  

Результирующий Java-код:

 public class ElementType {
    @XmlAttribute(name = "Group", required = true)
    protected int group;

    public int getGroup() {
        return group;
    }
    public void setGroup(int value) {
        this.group = value;
    }
}
  

Взято из руководства:

http://jaxb.java.net/tutorial/

Ответ №4:

Если у вас есть интерфейс конфигурации, такой как:

 public interface IConfig {
  int getNumber();
  void setNumber(int number);

  String getSomeProperty();
  void setSomeProperty(String someProperty);
}
  

затем вы могли бы использовать прокси для сопоставления методов со свойствами:

 public class ConfigWrapper implements InvocationHandler {
  @SuppressWarnings(value="unchecked")
  public static <T> T wrap(Class c, Properties p) {
    return (T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] {c},
        new ConfigWrapper(p));
  }

  private final Properties properties;

  private ConfigWrapper(Properties p) {
    this.properties = p;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) {
    if(method.getName().startsWith("get")) {
      if(method.getReturnType().equals(int.class)) {
        return Integer.parseInt(
            this.properties.getProperty(method.getName().substring(3)));
      } else if(method.getReturnType().equals(String.class)) {
        return this.properties.getProperty(method.getName().substring(3));
      } else {
        // obviously in a real application you'd want to handle more than just
        // String and int
        throw new RuntimeException(method.getName()   " returns unsupported type: "
              method.getReturnType());
      }
    } else if(method.getName().startsWith("set")) {
      this.properties.setProperty(method.getName().substring(3),
          args[0].toString());
      return null;
    } else {
      throw new RuntimeException("Unknown method: "   method.getName());
    }
  }
}
  

Чтобы использовать:

 Properties p = new Properties();

IConfig config = wrap(IConfig.class, p);

config.setNumber(50);
config.setSomeProperty("some value");
System.out.println(config.getNumber());
System.out.println(config.getSomeProperty());
System.out.println(p);
  

Вызов одного из методов интерфейса приводит к вызову ConfigWrapper.invoke() , который обновляет или извлекает данные из объекта Properties (в зависимости от того, вызывали ли вы средство получения или установки).

Обратите внимание, что эта реализация явно небезопасна, поскольку:

  • значения, уже имеющиеся в объекте Properties, не проверяются до тех пор, пока не будет вызван механизм получения
  • установщик и получатель не должны принимать / возвращать один и тот же тип

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

Ответ №5:

Моя библиотека Config4J (которая является зрелой и хорошо документированной, но не широко известной) предоставляет большую часть того, что вы хотите.

В частности, Config4J предоставляет типобезопасные операции «поиска» (то есть «получения») для встроенных типов, таких как string, boolean, int, float и длительности (такие как "500 milliseconds" или "2.5 days" ). Строка длительности автоматически преобразуется в целое значение, обозначающее (на ваш выбор) миллисекунды или секунды.

Библиотека также предоставляет стандартные блоки, позволяющие выполнять типобезопасный поиск строк вида "<float> <units>" (например, "2 cm" и "10.5 meters" для расстояний) или "<units> <float>" (например, "$0.99" или "£10.00" для денег).

Библиотека также предоставляет простой в использовании механизм проверки схемы (в случае, если это вас интересует).

Причина, по которой Config4J не соответствует вашим заявленным требованиям, заключается в том, что функциональность библиотеки «insert» (то есть «put») работает только в терминах строк. Итак, вам пришлось бы преобразовать значение int / boolean / float / int-denoting-duration / любое значение в строку, а затем «вставить» это в объект Config4J. Однако преобразование этого в строку обычно не является обременительной задачей.

После вставки некоторых пар имя = значение в объект Config4J вы можете затем вызвать dump() сериализацию всего объекта в строку, которую затем можно записать обратно в файл конфигурации.

Прочтение глав 2 и 3 «Руководства по началу работы» (PDF, HTML) должно дать вам достаточно хороший обзор Config4J, чтобы решить, соответствует ли он вашим потребностям. Возможно, вы также захотите взглянуть на демонстрационную версию «простой инкапсуляции», которая поставляется при загрузке исходного кода (сжатый tar, zip).

Комментарии:

1. Спасибо, я посмотрю. Кстати, где глава 1 на сайте? 🙂 Я вижу только 2-4

2. @FractalizeR: На www.config4star.org веб-сайт, прокрутите вниз до раздела «Загрузить руководства», и вы сможете получить доступ ко всем руководствам.

Ответ №6:

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

я думаю, что конфигурация commons — это лучший способ.

Ответ №7:

Вы должны быть в состоянии добиться некоторой отдачи, используя XStream для сериализации класса конфигурации. Но недостатки заключаются в:

  • Файл конфигурации не будет находиться ни в одном из стандартных форматов файла свойств. Вместо этого это будет произвольный XML.
  • Формат сериализации будет хрупким. Незначительные изменения в классе конфигурации могут сделать старые файлы конфигурации нечитаемыми.

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