Как создать свой собственный параметр приложения - PullRequest
1 голос
/ 22 мая 2010

Я хочу построить ApplicationSetting для моего приложения. ApplicationSetting может храниться в файле свойств или в таблице базы данных. Настройки хранятся в парах ключ-значение. Э.Г.

ftp.host = blade
ftp.username = dummy
ftp.pass = pass
content.row_pagination = 20
content.title = How to train your dragon.

Я спроектировал это следующим образом:

Считыватель настроек приложения:

    interface IApplicationSettingReader {
    Map read();
}

DatabaseApplicationSettingReader implements IApplicationSettingReader {
    dao appSettingDao;

    Map read() {
        List<AppSettingEntity> listEntity = appSettingsDao.findAll();
        Map<String, String> map = new HaspMap<String, String>();
        foreach (AppSettingEntity entity : listEntity) {
            map.put(entity.getConfigName(), entity.getConfigValue());
        }

        return new AppSettings(map);
    }
}

DatabaseApplicationSettingReader implements IApplicationSettingReader {
    dao appSettingDao;

    Map read() {
        //read from some properties file 
        return new AppSettings(map);
    }
}

Класс настроек приложения:

AppSettings {
private static AppSettings instance = new AppSettings();
private Map map;

private AppSettings() {
}



public static AppSettings getInstance() {
    if (instance == null) {
        throw new RuntimeException("Object not configure yet");
    } 

    return instance;
}

public static configure(IApplicationSettingReader reader) {
    this.map = reader.read();

}

public String getFtpSetting(String param) {
    return map.get("ftp." + param);
}

public String getContentSetting(String param) {
    return map.get("content." + param);
}

}

Тестовый класс:

AppSettingsTest {
    IApplicationSettingReader reader;

    @Before
    public void setUp() throws Exception {
        reader = new DatabaseApplicationSettingReader();
    }

    @Test
    public void  getContentSetting_should_get_content_title() {
        AppSettings.configure(reader);

        Instance settings = AppSettings.getInstance();
        String title = settings.getContentSetting("title");
        assertNotNull(title);
        Sysout(title);
    }

}

Мои вопросы:

  1. Можете ли вы высказать свое мнение о моем коде, что-то не так ?????

  2. Я настраиваю свои настройки приложения один раз, при запуске приложения я настраиваю настройку приложения с соответствующим считывателем (DbReader или PropertiesReader), я делаю его одноэлементным, потому что у приложения только один экземпляр ApplicationSettngs. Проблема в том, что когда пользователь редактирует базу данных или файл непосредственно в базе данных или файле, я не могу получить измененные значения. Теперь я хочу реализовать что-то вроде ApplicationSettingChangeListener. Поэтому, если данные изменятся, я обновлю настройки своего приложения. Есть ли у вас какие-либо предложения, как это можно реализовать? ????

Ответы [ 2 ]

0 голосов
/ 23 мая 2010

Ответ на вопрос № 2 состоит в том, чтобы использовать поток и периодически проверять, был ли файл изменен, или просто повторно инициализировать ваши настройки содержимым файла.

0 голосов
/ 23 мая 2010

Я не проверил ваш код тщательно, но, похоже, проблема с параллелизмом. Карта является поточно-небезопасной (HashMap), поэтому, если вы изменяете ее через config () и у других потоков есть карта доступа, у вас есть проблема.

Хотя вы можете использовать ConcurrentHashMap вместо HashMap, пакетная операция на ConcurrentHashMap не является атомарной. Это означает, что, если вы используете его, вы увидите «наполовину» модифицированный конфиг. Это не может быть хорошо в зависимости от вашего приложения.

Итак, решение для этого заключается в использовании этого:

private volatile ImmutableMap map;

public config(){
    ImmutableMap newMap = createNewMap();
    this.map = newMap;
}

Это изменит ваши конфиги атомарно (промежуточное состояние не видно).

Что касается обновления вашей конфигурации на лету, log4j делает это с помощью фонового потока, который контролирует файл конфигурации. Вы можете, конечно, контролировать таблицу БД, периодически опрашивая ее.

В этом случае ваш класс Config будет предпочтительно иметь ScheduledExecutor с задачей, которая будет периодически отслеживать файлы / db и вызывать config ().

...