2013-07-24 2 views
0

Я работаю над веб-приложением с пружиной. Приложение настроено с файлом свойств. Существует несколько экземпляров приложения на разных серверах, каждый экземпляр имеет другой файл конфигурации (каждый экземпляр настроен для другого клиента) Я использую контроллеры и службы. Что-то вроде этого:Впрыск пружинной зависимости в зависимости от объекта запроса

public class Controller1 { 
    @Autowired 
    Service1 service1; 

    @RequestMapping(value = "/page.htm", method = { RequestMethod.GET, RequestMethod.POST }) 
    public ModelAndView serve(HttpServletRequest request, HttpServletResponse response) { 
     service1.doSomething(); 
     return new ModelAndView("/something"); 
    } 
} 

@Service 
public class Service1 { 
    @Autowired 
    Service2 service2; 
    public void doSomething() { 
      … 
      service2.doAnotherThing(); 
      … 
     } 
} 

@Service 
public class Service2 { 
    @Value("${propertyValue}") 
    private String propertyValue; 

    //doAnotherThing() will use propertyValue 
    public void doAnotherThing() { 
     … 
     //Do something with propertyValue 
     … 
     } 
} 

Теперь у меня есть новое требование. Для каждого клиента не будет нескольких экземпляров, но только один экземпляр с несколькими доменами для всех клиентов. Приложение должно определить конфигурацию в зависимости от имени хоста объекта запроса в контроллере. Поэтому, если клиент указывает браузер на www.app1.com, я должен использовать конфигурационный файл 1, но если клиент использует www.app2.com, я должен использовать конфигурацию 2 и так далее.

Я переместил файлы конфигурации в базу данных, но потом понял, что не знаю, как сделать инъекцию зависимостей. Службы связаны, service1 использует service2, а service2 - тот, кто должен использовать значение, зависящее от конфигурации. Сервис 2 не знает объект запроса.

Есть ли чистый способ решить эту проблему?

Спасибо,

ответ

1

Один подход заключается в создании объекта конфигурации для всех клиентов, как одноточечные на весенней конфигурации:

<bean id="customerAConfig"../> 
<bean id="customerBConfig"../> 
<bean id="customerCConfig"../> 

И есть сеанс области видимости ConfigurationService, который действует как указатель на который configuartion активно

public class ConfigurationService { 

    private CustomerConfig activeConfig; 

    // getters & setters.. 
} 

Настройка одноэлементен прокси для этого сервиса на вашей весенней конфигурации, поэтому он может быть введен в одноэлементные компоненты. Вы должны иметь CGLIB в вашем пути к классам для Spring для создания прокси-сервера:

<bean class="com.mycompany.ConfigurationService" scope="session"> 
    <aop:scoped-proxy/> 
</bean> 

А на контроллере входа, выберите, какая конфигурация должна использоваться имя виртуального хоста и сохранить его в ConfigurationService для последующего извлечения (помните ConfigurationService является сессии областью действия)

public class LoginController { 

    @Autowired private CustomerConfig[] custConfigs; 
    @Autowired private ConfigurationService configService; 

    @RequestMapping(method = POST) 
    public String login(HttpServletRequest request, ..) { 
    ... 
    String host = request.getServerName(); 
    CustomerConfig activeConfig = // decide which one based on host.. 
    configService.setActiveConfig(activeConfig); 
    ... 
    } 
} 

Ниже приведен пример FooController, который считывает клиентов конкретной конфигурации

@Controller 
@RequestMapping("/foo") 
public class FooController { 

    @Autowired private ConfigurationService configService; 

    @RequestMapping(method = "GET") 
    public String get() { 
    ... 
    CustomerConfig config = configService.getActiveConfig(); 
    ... 
    } 

    ... 
} 

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

Смежные вопросы