Можно ли динамически менять профили во время выполнения?

#spring-boot

#весенняя загрузка

Вопрос:

Я модернизирую устаревшее веб-приложение. Одна из сложностей в этом приложении — модель конфигурации. В настоящее время у каждого клиента есть отдельный экземпляр приложения с отдельными свойствами конфигурации для каждого экземпляра. В настоящее время свойства хранятся в Tomcat context.xml , и есть помощник JNDI для извлечения этих свойств при запуске. Поскольку один экземпляр Tomcat = один context.xml , это работает. Но теперь нам нужен один экземпляр (или кластер экземпляров) для всех клиентов.

Я думаю, что обычно это делается во время сеанса. Но в этом случае это был бы большой рефакторинг. Значения конфигурации хранятся в pojo со статическими установщиками и получателями, которые часто вызываются по всей кодовой базе. Помощник JNDI устанавливает конфигурацию в pojo при запуске, и именно так приложение находит свои значения конфигурации.

Мы делаем небольшие шаги при разработке, чтобы улучшить эту модель, а не проводить большой рефакторинг. Итак, цель состоит в том, чтобы изменить как можно меньше, двигаясь в правильном направлении. Одной из вещей, которые я рассматривал, было использование профилей весенней загрузки. Вместо отдельного экземпляра для каждого клиента может быть профиль весенней загрузки для каждого клиента. Затем, при каждом HTTP-запросе, фильтр сервлетов может активировать соответствующий профиль, наблюдая за пользователем и активируя его профиль на время выполнения запроса, который, я надеюсь, сможет затем вводить значения в статические установщики из фильтра.

Я знаю, что это ненормально, но я пытаюсь мыслить нестандартно.

Я знаю о ConfigurableEnvironment.setActiveProfiles. В чем я не уверен, так это в том, будет ли это активно вводить изменения значений свойств после фазы начальной загрузки, а также может ли это вызвать проблемы с производительностью или по какой-либо другой причине звучит безумно.

Ответ №1:

Из документации Spring:

Вы можете программно установить активные профили, вызвав SpringApplication.setAdditionalProfiles(…​) их перед запуском вашего приложения. Также можно активировать профили с помощью ConfigurableEnvironment интерфейса Spring.

Ответ №2:

Это не имеет ничего общего с spring profiles! Вы можете управлять ими программно, но в какой-то момент у вас есть один контекст spring в вашей JVM (приложении). Вы хотите работать с пользовательскими свойствами, не так ли? Это для каждого запроса или, скорее, для области сеанса, а не для области приложения! Я предлагаю вам следующий сценарий:

1.) после аутентификации вашего клиента сохраните его значения в экземпляре CustomerConfig (не статическом!) И сохраните этот customerConfig в атрибутах запроса или сеанса

2.) вы можете сделать это в HttpFilter :

 if (session.isNew)
{   // read customerConfig from DB or resources etc...
    session.setAttribute("customerConfig",customerConfig);
}
 

3.) в ваших классах POJO вы можете получить доступ к нему следующим образом

 ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
CustomerConfig cc =(CustomerConfig)attr.getRequest().getSession().getAttribute("customerConfig");
parameter = cc.getYourCustomerProperty();
 

4.) В ваших компонентах, сервисах и т. Д. Вы можете автоматически выполнить запрос, например:

 @Component
@Scope("request")
public class FooBar {
    @Autowired 
    private HttpServletRequest request;

    public void function()
    { CustomerConfig config = request().getSession().getAttribute("customerConfig");
      parameter = cc.getYourCustomerProperty();
      //...
     }  
}
 

Комментарии:

1. Звучит здорово, спасибо. RequestContextHolder — это именно то, что мне нужно.