[ главная ]   [ рейтинг статей ]   [ справочник радиолюбителя ]   [ новости мира ИТ ]



Ответов: 0
25-02-12 07:01







   Web - программирование
PHP


ASP






XML



CSS

SSI





   Программирование под ОС











   Web - технологии








   Базы Данных









   Графика






Данные




Программирование под ОС / Java /

Как хранить настройки java программ?

Этот вопрос задает себе каждый разработчик любого серьезного приложения. Классическим решением этой задачи является использование класса Properties. Этот класс поддерживает коллекции свойств (properties) вида ключ/значение, где ключи и значения являются строками. Наличие методов сохранения и чтения коллекций в файлах, упрощает организацию физического хранения данных. Несмотря на удобство ...

Этот вопрос задает себе каждый разработчик любого серьезного приложения. Классическим решением этой задачи является использование класса Properties. Этот класс поддерживает коллекции свойств (properties) вида ключ/значение, где ключи и значения являются строками. Наличие методов сохранения и чтения коллекций в файлах, упрощает организацию физического хранения данных. Несмотря на удобство и простоту использования данного класса хочется обратить ваше внимание, что класс Properties является наследником устаревшего класса Hashtable [1]. Именно по этому рекомендуется использовать класс HashMap, который является аналогом Hashtable.

Для доступа к настройкам программы создадим класс AppSettings. Причем в блоке инициализации статических членов класса будет вызываться private конструктор данного класса. При этом создается единственный экземпляр данного объекта в статическую переменную SINGLETON при первом вызове из основного кода программы. Код, реализующий эту методику имеет вид:

public class AppSettings {
  private AppSettings() {
    fHashMap = new HashMap();
  }
  . . .

  private HashMap fHashMap;
  private static AppSettings SINGLETON;
  static {
    SINGLETON = new AppSettings();
  }
}

Таким образом к единственному экземпляру данного класса можно получить доступ из любого модуля программы, что напоминает глобальные переменные в других языках программирования. Коллекция HashMap позволяет хранить различные объекты, но мы пока ограничимся только строковыми. Методы доступа к данным могут иметь вид:

// Извлечение объекта из коллекции
public static Object get(String key) {
  return SINGLETON.fHashMap.get(key);
}

// Извлечение объекта из коллекции
// при отсутствии данных возвращается значение по умолчанию
public static Object get(String key, Object deflt) {
  Object obj = SINGLETON.fHashMap.get(key);
  if (obj == null) {
    return deflt;
  } else {
    return obj;
  }
}

// Для упрощения извлечения данных типа int
public static int getInt(String key, int deflt) {
  Object obj = SINGLETON.fHashMap.get(key);
  if (obj == null) {
    return deflt;
  } else {
    return new Integer((String) obj).intValue();
  }
}

// Добавление объекта в коллекцию
public static void put(String key, Object data) {
  //prevent null values. Hasmap allow them
  if (data == null) {
    throw new IllegalArgumentException();
  } else {
    SINGLETON.fHashMap.put(key, data);
  }
}

Раз уж мы отказались от использования класса Properties, то изменим формат хранения объектов коллекции на более прогрессивный xml формат. Структура xml файла будет иметь вид:

<?xml version = '1.0'?>
<app-settings>
 <properties>
  <property key="MainFrame.height">319</property>
  <property key="MainFrame.width">424</property>
  <property key="LookAndFeel">
   com.sun.java.swing.plaf.motif.MotifLookAndFeel</property>
 </properties>
</app-settings>

Данная структура позволит нам в будущем хранить не только значения вида ключ/значение, но и другие типы объектов. Пока же, мы ограничимся строками, аналогично классу Properties. Код построения DOM дерева заданной структуры и трансформации в xml файл будет иметь вид:

public static boolean save(File file) throws Exception {
  // Создаем новое DOM дерево
  DOMImplementation domImpl = new DOMImplementationImpl();
  Document doc = domImpl.createDocument(null, "app-settings", null);
  Element root = doc.getDocumentElement();
  Element propertiesElement = doc.createElement("properties");
  root.appendChild(propertiesElement);
  Set set = SINGLETON.fHashMap.keySet();
  if (set != null) {
    for (Iterator iterator = set.iterator(); iterator.hasNext(); ) {
      String key = iterator.next().toString();
      Element propertyElement = doc.createElement("property");
      propertyElement.setAttribute("key", key);
      Text nameText = doc.createTextNode(get(key).toString());
      propertyElement.appendChild((Node) nameText);
      propertiesElement.appendChild(propertyElement);
    }
  }
  // Сериализируем DOM дерево в файл
  DOMSerializer serializer = new DOMSerializer();
  serializer.serialize(doc, file);
  return true;
}

Класс сериализации DOM дерева позаимствован в [2]. Для обратной операции чтения данных в коллекцию создадим следующий метод:

public static boolean load(File file) throws Exception {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  DocumentBuilder builder = factory.newDocumentBuilder();
  Document doc = builder.parse(file);
  if (doc == null) {
    throw new NullPointerException();
  }
  NodeList propertiesNL = doc.getDocumentElement().getChildNodes();
  if (propertiesNL != null) {
    for (int i = 0; (i < propertiesNL.getLength()); i++) {
      if (propertiesNL.item(i).getNodeName().equals("properties")) {
        NodeList propertyList = propertiesNL.item(i).getChildNodes();
        for (int j = 0; j < propertyList.getLength(); j++) {
          NamedNodeMap attributes = propertyList.item(j).getAttributes();
          if (attributes != null) {
Node n = attributes.getNamedItem("key");
NodeList childs = propertyList.item(j).getChildNodes();
if (childs != null) {
  for (int k = 0; k < childs.getLength(); k++) {
    if (childs.item(k).getNodeType() == Node.TEXT_NODE) {
      put(n.getNodeValue(), childs.item(k).getNodeValue());
    }
  }
}
          }
        }
      }
    }
    return true;
  } else {
    return false;
  }
}

А пример вызова методов класса AppSettings в теле программы, показан в следующем участке кода:

File file = new File(propDir, "settings.xml");
try {
  AppSettings.clear();
  AppSettings.load(file);
  String lnfName = UIManager.getLookAndFeel().getClass().getName();
  if (AppSettings.get(LF_KEY, lnfName) != lnfName) {
    UIManager.setLookAndFeel(
    (String) AppSettings.get(LF_KEY, lnfName));
    SwingUtilities.updateComponentTreeUI(MainFrame.this);
  }

  this.setSize(new Dimension(
  AppSettings.getInt(WIDTH_KEY, getWidth()),
  AppSettings.getInt(HEIGHT_KEY, getHeight())
  ));
} catch (Exception e) {
  e.printStackTrace();
}

Как видно из приведенного кода, все достаточно тривиально. Просто вызываем нужный метод класса AppSettings создавать экземпляр которого не требуется. Можно реализовать еще пару методов для извлечения часто используемых типов данных для удобства использования, например getString().

Литература:

  1. Арнольд Кен, Гослинг Джеймс, Холмс Дэвид. “Язык программирования Java”. Пер. С англ. - М.: Издательский дом “Вилиамс”, 2001. - 624 с. ISBN 5-8459-0215-0 (рус.)
  2. Brett McLaughlin “Java& XML, 2nd Edition”Publisher: O'Reilly. Second Edition September 2001. ISBN: 0-596-00197-5, 528 pages
Автор: Сергей Бердачук, 31.01.2004
http://www.berdaflex.com



Комментарии

 Ваш комментарий к данному материалу будет интересен нам и нашим читателям!



Последние статьи: Программирование под ОС / Java /

Особенности Java 5
23-02-2010   

Java 5 обладает некоторыми полезными возможностями. В данной статье мы рассмотрим их и узнаем, как можно извлечь из них выгоду. В этой части мы рассмотрим auto-boxing foreach... подробнее

Кол. просмотров: общее - 5284 сегодня - 0

Особенности Java 5. Часть 2
23-02-2010   

В первой части мы обсудили новые возможности Java 5 относительно функции auto-boxing и цикла foreach. В данной части мы обсудим поддержку функций с переменным числом аргументов и статическое импортирование (static import). Поскольку другие функции, такие как enum, annotation, и generics, заслуживают отдельной статьи, мы их не будет демонстрировать в данной... подробнее

Кол. просмотров: общее - 4398 сегодня - 0

Расширение функциональности элементов пользовательского интерфейса в Java
05-05-2009   

Довольно часто при создании приложений с GUI (stand alone приложений или апплетов) приходится сталкиваться с необходимостью несколько изменить внешний вид и поведение стандартных компонентов пользовательского интерфейса... подробнее

Кол. просмотров: общее - 4661 сегодня - 0

Введение в сервлеты
05-05-2009   

Что такое сервлет ? Это класс порожденный от класса HttpServlet с переопреденными методами doGet и doPost (управление приходит в один из этих методов в зависимости от того какого типа был запрос. Надеюсь у Вас есть некоторый опыт в cgi-программировании... подробнее

Кол. просмотров: общее - 4350 сегодня - 0

Java Server Pages
05-05-2009   

Технология Java Server Pages (JSP) является составной частью единой технологии создания бизнес-приложений J2EE. JSP - это альтернативная методика разработки приложений... подробнее

Кол. просмотров: общее - 4397 сегодня - 0



  WWW.COMPROG.RU - 2009-2012 | Designed and Powered by Zaipov Renat | Projects