0

我正在使用 spring 开发一个 web 应用程序。该应用程序配置有一个属性文件。应用程序在不同的服务器中有多个实例,每个实例都有不同的配置文件(每个实例都是为不同的客户定制的)我正在使用控制器和服务。像这样的东西:

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 不知道请求对象。

有没有一种干净的方法来解决这个问题?

谢谢,

4

1 回答 1

1

一种方法是在 spring config 上为所有客户创建配置对象作为单例:

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

并有一个会话范围的 ConfigurationService,它充当指向哪个配置处于活动状态的指针

public class ConfigurationService {

   private CustomerConfig activeConfig;

   // getters & setters..
}

在你的 spring 配置中为这个服务配置一个单例代理,这样它就可以被注入到单例组件中。您需要在 Spring 的类路径中包含 cglib 才能创建代理:

<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();
    ...
  }

  ...
}

如果您的程序没有像登录页面这样的单一入口点,您可以编写类似的逻辑作为过滤器。检查是否在会话上设置了活动配置,如果没有根据主机名查找它

于 2013-07-24T05:33:55.430 回答