Properties w Javie – Tworzymy globalną konfigurację

Nie raz, nie dwa zdarzyło się na pewno niektórym pisać aplikację, która wymagała stworzenia globalnej konfiguracji. Do osiągnięcia tego celu jest mnóstwo metod, przedstawię tutaj swoje podejście, jednocześnie zaznaczając, że nie jest ono jedyne i wcześniej warto poświęcić chwilę żeby sprawdzić czy będzie ono najlepsze dla pisanej aplikacji.

Metoda, którą przedstawię, bazuje na singletonie. Wartości przechowywane są w plikach *.properties w folderze z zasobami. Zacznijmy od zdefiniowania naszego singletonu.
[java]
public enum Configuration
{
    INSTANCE;
    Map<String, String> settings;

    Configuration()
    {

        Properties properties = new Properties();
        try (InputStream propertiesStream =
getClass().getResourceAsStream("config.properties"))
        {
            properties.load(propertiesStream);
            settings = Maps.newHashMap((Map) properties);
propertiesStream.close();
        } catch (Exception ex)
        {
            // Handle an exception
        }
    }
}[/java]
I w tym momencie niektórzy zadadzą sobie pytanie: „Co jest k… z tym enumem?”. Otóż jest to nowa (nowa jak nowa, wprowadzona od wersji 1.5), preferowana możliwość tworzenia singletonów.

Owe podejście jest funkcjonalnie takie samo jak metoda z publicznym polem, poza tym, że jest zwięzłe, automatycznie wprowadza mechanizm serializacji oraz zapewnia 100% gwarancję unikalności. (…) jednoelementowy typ enum  jest najlepszym sposobem na implementację singletonu.

„Effective Java (2nd Edition)”

Po szybkim przeskanowaniu kodu można zauważyć, że używam mechanizmu HashMap do przechowywania ustawień w trakcie działania programu. Wg mnie jest to dobre podejście zwłaszcza, że klasa Properties dostarcza gotowy mechanizm konwersji zarówno z map jak i do nich.

W linijce 15. widać, że przetworzenie obiektu Properties na mapę, ogranicza się jedynie do przekazania go do konstruktora mapy.

WAŻNE

Metoda Maps.newHashMap() pochodzi z biblioteki Google Guava, jeżeli jej nie posiadamy, to zamiast tego musimy bezpośrednio użyć konstruktora HashMap.

Żeby nasza klasa zyskała na funkcjonalności, potrzebny jest jeszcze mechanizm pobierania i zapisywania konkretnych ustawień.

[java]
public String getValue(String key)
{
    return settings.get(key);
}

public void setValue(String key, String value)
{
    settings.put(key, value);
}[/java]
Ta część akurat nie wymaga większych wyjaśnień, proste zapisywanie i odczytywanie z mapy. Warto jednak zwrócić uwagę na to, jakie typy są przyjmowane i zwracane przez funkcje, należy je dobrać tak, aby były zgodne z deklaracją naszej mapy; w moim programie akurat zarówno klucze jak i wartości są ciągami.

Niby wszystko jest, ale jednak czegoś brak. Czymże byłyby ustawienia, które się nie zapisują? Na pewno świetnym sposobem na poirytowanie użytkownika szczególnie, gdy jest ich dużo. W takim razie przyda się ostatnia metoda, która ustawienia zapisane w mapie, zapisze do pliku.
[java]
public void store()
{
Properties properties = new Properties();

properties.putAll(settings);
try
{
FileOutputStream outputStream = new FileOutputStream(getClass()
.getResource("config.properties").getFile());
properties.store(outputStream, null);
outputStream.close();
} catch (FileNotFoundException ex)
{
// Handle an exception
} catch (IOException ex)
{
// Handle an exception
}

}[/java]

Jak tego używać?

Nic prostszego, w dowolnym miejscu w programie należy wywołać np.
[java light=”true”]Configuration.INSTANCE.setValue("any_key", "any_param");[/java]

A konstruktor?

Jest wywoływany automatycznie przy inicjalizacji enuma.

[guest@itachi.pl:~]$

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *