我正在Spring启动服务,从Spring云中获取配置。这些服务是多租户,租户基于主机名。
我现在拥有的是
public class MyController {
@Autowired
public MyController(MyServiceFactory factory) {
...
}
@RequestMapping("some/path/{id}")
ResponseEntity<SomeEntity> getSomeEntity(@RequestHeader header, @PathVariable id) {
return factory.getMyService(header).handle(id);
}
}
MyServiceFactory看起来像......
public class MyServiceFactory {
private final HashMap<String, MyService> serviceRegistry = new HashMap<>();
public MyService getMyService(String key) {
return serviceRegistry.get(key);
}
MyServiceFactory withService(String key, MyService service) {
this.serviceRegistry.put(key, service);
return this;
}
}
然后在配置文件中
@Configuration
public ServiceFactoryConfiguration {
@Bean
public MyServiceFactory getMyServiceFactory() {
return new MyServiceFactory()
.withService("client1", new MyService1())
.withService("client2", new MyService2());
}
}
虽然我现在的工作原理,我不喜欢我需要为我的控制器可能拥有的每个依赖项创建一个工厂。我想让我的代码看起来像这样...
public class MyController {
@Autowired
public MyController(MyService service) {
...
}
@RequestMapping("some/path/{id}")
ResponseEntity<SomeEntity> getSomeEntity(@PathVariable id) {
return service.handle(id);
}
}
使用类似
的配置文件@Configuration
public class MyServiceConfiguration() {
@Bean
@Qualifier("Client1")
public MyService getMyService1() {
return new MyService1();
}
@Bean
@Qualifier("Client2")
public MyService getMyService2() {
return new MyService2();
}
}
如果我在应用程序启动时使用配置文件,我可以获取我想要编写的代码。但我希望有许多不同的DNS记录指向同一个(池)实例,并且有一个实例能够处理不同客户端的请求。我希望能够根据每个请求交换配置文件。
这可能吗?
答案 0 :(得分:1)
Spring配置文件在这里没有帮助,每个客户端需要一个应用程序上下文,这似乎不是你想要的。
相反,你可以使用scoped bean。 使用范围“client”创建客户端相关bean:
public class ClientScope implements Scope {
@Autowired
BeanFactory beanFactory;
Object get(String name, ObjectFactory<?> objectFactory){
//we do not use the objectFactory here, instead the beanFactory
//you somehow have to know which client is the current
//from the config, current request, session, or ThreadLocal..
String client=findCurrentClient(..);
//client now is something like 'Client1'
//check if your cache (HashMap) contains an instance with
//BeanName = name for the client, if true, return that
..
//if not, create a new instance of the bean with the given name
//for the current client. Easiest way using a naming convention
String clientBeanName=client+'.'+name;
Object clientBean=BeanFactory.getBean(clientBeanName);
//put in cache ...
return clientBean;
};
}
将至少有3个MyService类型的bean:作用域,每个客户端一个。注释@Primary告诉spring总是使用scoped bean进行注入。
创建范围:
@Bean('Client1.myService')
public MyService getMyService1() {
return new MyService1();
}
@Bean('Client2.myService')
public MyService getMyService2() {
return new MyService2();
}
您的客户特定bean配置如下:
success: function(response) {
var resp = JSON.parse(response);
alert(resp.text); // Login success or Fail
}
没有测试它,但在我的项目中使用它。应该工作。