Java использование Properties глобально

197
19 октября 2018, 20:30

Как правильно использовать java.util.Properties в приложении? Важны такие требования:

  • Конфиг должен быть доступен с диска для редактирования, а не быть в .jar
  • Приложение запускается под кроном, поэтому надо избежать проблем с абсолютными путями
  • Конфиг должен быть доступен во многих классах программы

Насчет последнего пункта, как это можно сделать? Использовать синглтон?

package properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Main {
    public static void main(String[] args) throws IOException {
        final String configPath = "src/main/resources/config.properties";
        Properties props = new Properties();
        props.load(new FileInputStream(configPath));
        System.out.println(props.getProperty("mode"));
    }
}
Answer 1

Если нужно разместить properties файл рядом с jar, можно использовать такой код

Properties props = new Properties();
// Получаем путь к jar
URI uri = MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI();
// Получаем каталог jar файла
String path = new File(uri).getParent();
log.debug(() -> "Load properties from " + path);
// Загружаем конфиг
try (InputStream file = new FileInputStream(path + "/connection.properties")) {
    props.load(file);
}

Но очень часто у обычного пользователя не будет прав на редактирование файлов в этом каталоге. Если такое поведение не устраивает, то можно разместить properties файл в домашнем каталоге пользователя. Путь к каталогу можно получить так

String path = System.getProperty("user.home");
Answer 2

По поводу доступности везде. Есть достаточно хорошая реализация расширителя Properties().

Код ExProperty.java

public class ExProperties extends Properties
{
    private static final long serialVersionUID = 1L;
    public void load(final String fileName) throws IOException
    {
        load(new File(fileName));
    }
    public void load(final File file) throws IOException
    {
        try (InputStream is = new FileInputStream(file))
        {
            load(is);
        }
    }
    public boolean getBoolean(final String name, final boolean defaultValue)
    {
        boolean val = defaultValue;
        final String value;
        if ((value = super.getProperty(name, null)) != null)
            val = Boolean.parseBoolean(value);
        return val;
    }
    public String getString(final String name, final String defaultValue)
    {
        String val = defaultValue;
        final String value;
        if ((value = super.getProperty(name, null)) != null)
            return value;
        return val;
    }
    public int getInteger(final String name, final int defaultValue)
    {
        int val = defaultValue;
        final String value;
        if ((value = super.getProperty(name, null)) != null)
            val = Integer.parseInt(value);
        return val;
    }
    public long getLong(final String name, final long defaultValue)
    {
        long val = defaultValue;
        final String value;
        if ((value = super.getProperty(name, null)) != null)
            val = Long.parseLong(value);
        return val;
    }
    public double getDouble(final String name, final double defaultValue)
    {
        double val = defaultValue;
        final String value;
        if ((value = super.getProperty(name, null)) != null)
            val = Double.parseDouble(value);
        return val;
    }
}

Код Prop.java

public final class Prop
{
    public static ExProperties _properties;
    public static int TEST_INTEGER;
    public static long TEST_LONG;
    public static final void load()
    {
        _properties = initProperties("filename.properties");
        TEST_INTEGER = _properties.getInteger("testInteget", -1);
        TEST_LONG = _properties.getLong("testLong", -1L);
    }
    public static final ExProperties getProperties()
    {
        return _properties;
    }
    public static final ExProperties initProperties(String filename)
    {
        final ExProperties result = new ExProperties();
        try
        {
            result.load(new File(filename));
        }
        catch (Exception e)
        {
            System.out.println("An error occured loading '" + filename + "' properties.");
        }
        return result;
    }
}

Варианты использования:

public class Test
{
    public static void main(String[] args)
    {
        Prop.load();
        final int testInt_1 = Prop.TEST_INTEGER;
        final int testInt_2 = Prop.getProperties().getInteger("testInteger", -1);
    }
}

Если файл с конфигурацией будет лежать рядом с исполняемым файлом, то не вижу смысла указывать пути через вычисление местоположение исполняемого файла. Можно просто указать где искать относительно JAR.

_properties = initProperties("./Properties.properties");
READ ALSO
Java выполнение повторяющихся заданий

Java выполнение повторяющихся заданий

Есть сервис, который надо запускать периодическиКак лучше реализовать периодическое выполнение задания на джаве? Какие "за" и "против" использования...

163
Как создать объект типа T

Как создать объект типа T

У меня есть метод с параметром

183
Java. События кнопки

Java. События кнопки

Учу события кнопки и не могу решить задачу, тк не понимаю с областями видимости и со смыслом

197
Следить за Log-ами приложения

Следить за Log-ами приложения

UPDATED Как правильно записывать логи в файл в приложении, что проверяют тестировщики?

218