Программная установка значения свойств в SpringBoot

У меня есть приложение, в котором есть функция, которая включается или отключается с помощью параметра в application.properties, например

app.thingEnabled=true

И, конечно, это может быть правдой или ложью. И у меня в контроллере:

@Value("${app.thingEnabled:true}")
private boolean thingEnabled;

Конечно, мы проверяем, правда это или ложь, а затем либо делаем, либо не делаем.

Теперь я хочу, чтобы у этого был механизм обратной связи ... Например, функция Thing Feature записывает в базу данных. Если код БД обнаруживает исключение тайм-аута, установите для thingEnabled значение false на 5 минут, а затем повторите попытку. Что-то в этом роде.

Возможно ли это весной? Я подумал о создании отдельного компонента как, скажем, «ThingConfiguration», который мог бы иметь свойства, установленные на нем, а затем связать это свойство с ним, и контроллер просто вызвал бы его. Тогда у него может быть геттер и сеттер, которые могут обновляться динамически, но, похоже, может быть лучший способ.

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

Во-вторых, есть ли способ запустить поток, который спит эти 5 минут, а затем выполняет некоторую работу, не копаясь в api потоковой передачи низкого уровня? Я вижу, что есть @Scheduled, но похоже, что он предназначен для выполнения некоторой работы снова и снова, а не как что-то, инициированное самим кодом.

Какова ваша конечная цель? Управляет ли это логическое значение чем-то, что можно легко внедрить, или бизнес-логикой? То есть, это контролирует, используете ли вы конкретный инъекционный компонент, или это контролирует, если вы идете по одному логическому пути над другим?

Makoto 20.04.2018 18:09

Он контролирует, следует ли код по тому или иному пути.

MichaelB 20.04.2018 18:10

Что мешает сделать для него сеттер (я думаю, он у вас уже есть)? затем изменить его значение вперед и назад в зависимости от тайм-аута БД или чего-то еще?

Vadim 20.04.2018 18:13

Тогда возникает вопрос, как получить доступ к этому компоненту из другого места в коде, и если вам нравится @Autowired, ThingController - это один и тот же экземпляр для всех потоков выполнения? Или это изменит только свойство одного в том же потоке?

MichaelB 20.04.2018 18:15

Пока я знаю ... простой @Autowired указывает на один экземпляр singleton для всех потоков. Одноэлементный режим по умолчанию для Spring beans.

Vadim 20.04.2018 18:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
126
2

Ответы 2

Одна из вещей, которые вы, вероятно, захотите отделить, - это право на участие ваших запросов, выполняемых из их активация. thingEnabled определяет, активирован ли ваш процесс. Что-то еще должно определять, нужно ли запускать имеющий право.

В конечном итоге это зависит от того, как вы пишете свои запросы, но в Spring нет ничего, что могло бы спать в течение X минут, а затем обновлять ваш запрос. Однако, если вы разделите логику для определения права на участие, то написать что-нибудь, чтобы проверить, соответствуют ли временные отклонения вашему критерию, станет несколько проще. (Я оставляю это в качестве упражнения для читателя).

Чтобы ответить на заголовок:

Setting value of properties programatically in SpringBoot

Spring будет искать аннотации @Value только при запуске приложения, он не будет обновляться сам по себе после первого экземпляра. Например:

@Value("${app.thingEnabled:true}")
private boolean thingEnabled;

Это установит для thingEnabled значение, которое вы установили в application.properties, или true, если это свойство не найдено.

После этого, если вы установите для thingEnabled значение false, оно останется ложным. По сути, Spring будет назначать значение thingEnabled только при запуске, и никаких изменений вноситься не будет, если вы не сделаете их самостоятельно.

В твоем случае,

Now, I want to make this have a feedback mechanism... Like, the Thing Feature writes to a database. If the DB code catches a timeout exception, set thingEnabled to false for 5 mins and then try again.

Примерно так:

// database operation...
} catch (SQLTimeoutException e) {
    thingEnabled = false; 
    // start a timerTask that will run in 5 minute, and then execute your code again
}

Но thingEnabled в данном случае не актуален, и я не понимаю, что вы здесь имеете в виду под feedback.

Я предполагаю, что вместо этого вы имели в виду запасной вариант.

В этом случае вы должны сделать следующее:

// database operation...
} catch (SQLTimeoutException e) {
    if (thingEnabled) { // if the fallback is enabled
        // start a timerTask that will run in 5 minute, and then execute your code again
    }
}

Таким образом, установка app.thingEnabled действительно будет актуальна:

  • если app.thingEnabled - это true, повторите попытку через 5 минут после исключения из тайм-аута
  • если app.thingEnabled - это false, не пытайтесь повторить попытку.

Вы можете прочитать о Таймер и TimerTask. Также хороший пример можно найти здесь.

TimerTask не очень хорошо работает со Spring ... Каждую задачу необходимо создавать индивидуально, поэтому вы не можете автоматически подключать компоненты, управляемые Spring, в TimerTask.

MichaelB 20.04.2018 18:59

@MichaelB Пока объект TimerTask находится внутри компонента, к нему можно получить доступ через автоматическое подключение самого компонента и доступ к TimerTask через него. В конечном итоге вы можете использовать ScheduledExecutorService, но Spring все еще не управляет этим.

TwiN 20.04.2018 19:15

Пример: ConfigReset cr - это автоматическое расширение TimerTask. Потом Timer timer = new Timer(); timer.schedule(cr, Date.from(Instant.now().plusSeconds(10)));. Он работает один раз, а затем вы получаете java.lang.IllegalStateException: Task already scheduled or cancelled, потому что вам нужен новый экземпляр класса TimerTask

MichaelB 20.04.2018 19:42

Другие вопросы по теме