Spring Solr - 将多个客户端用于不同的服务

Spring Solr - Using multiple clients to different services

我正在使用一个聚合来自多个来源的数据的应用程序。在这种情况下,我需要使用不相关的数据连接到两个不同的 Solr 服务。为此,我建立了两个不同的数据存储库。我将 bean 定义如下:

@Configuration
@EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.gcr"}, multicoreSupport=true)
public class GcrSolrContext {

    @Bean
    public SolrClient solrClient() {
        return new HttpSolrClient("http://foo:8086/solr/gcr");
    }

    @Bean
    public SolrTemplate solrTemplate(SolrClient client) throws Exception {
        return new SolrTemplate(client);
    }
}

我遇到的问题是我不知道如何拥有两个完全独立的 Solr 客户端,每个客户端都指向不同的 url。由于需要 bean solrClient() 和 solrTemplate(),并且尝试创建具有不同 URLs 的新 Context 只会让 solrClient 和 solrTemplate bean 被首先创建的 bean 覆盖。如果每个客户端是唯一定义的 Solr 客户端,它们都可以正常工作。

简而言之,我如何创建两个(或更多)不同的 Spring Solr 客户端,每个都连接到不同的 URLS?

附加信息是对评论的回应...

我试图用以下不同的 configurations.Consider 简单地重新创建 SolrContext class:

@Configuration
@EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.different"}, multicoreSupport=true)
public class DifferentSolrContext {

    @Bean
    public SolrClient solrClient() {
        return new HttpSolrClient("http://SomethingDifferent:8086/solr/something");
    }

    @Bean
    public SolrTemplate solrTemplate(SolrClient client) throws Exception {
        return new SolrTemplate(client);
    }
}

这里发生的是在启动期间创建 bean 时 @Bean 的 solrClient 和 solrTemplate 被覆盖。

INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'solrClient' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=yyySolrContext; factoryMethodName=solrClient; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.GcrSolrContext] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=xxxSolrContext; factoryMethodName=solrClient; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.XxxSolrContext]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'solrTemplate' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=yyySolrContext; factoryMethodName=solrTemplate; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.GcrSolrContext] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=haystackSolrContext; factoryMethodName=solrTemplate; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.XxxSolrContext]

测试表明 URL 确实只是第一个实例化的 bean。我还尝试将第二个上下文 bean 重命名为其他名称,但是 Solr 功能无法 locate/identify bean。

这是在尝试定义多个 SolrClient 时抛出的错误。

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.apache.solr.client.solrj.SolrClient' available: expected single matching bean but found 2: solrClient2,solrClient

简而言之,对于 Spring Solr 数据库,似乎只有一个 URL 是可能的。 (注意:使用版本 2.1.4)是否有人在 Spring Solr 数据下工作超过一个 URL(不仅仅是核心)?

为 spring 创建另一个 bean 以使用 solr,这既简单又干净:

@Configuration
@EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.xxx"}, multicoreSupport=true)
public class XXXSolrContext {

    @Bean
    public SolrClient getClient() {
        return new HttpSolrClient("http://foo:8086/solr/xxx");
    }

    @Bean
    public SolrTemplate getTemplate(SolrClient client) throws Exception {
        return new SolrTemplate(client);
    }
}

由于在同一个 Spring 上下文中有多个相同类型的 bean,因此在使用自动装配时需要消除歧义。以下应该有效:

Configuration for first Solr server

@Configuration
public class PrimarySolrContext {
  @Bean
  public SolrClient primarySolrClient() {
    return new HttpSolrClient(...);
  }

  @Bean("primary")
  public SolrTemplate solrTemplate() {
    return new SolrTemplate(primarySolrClient());
  }
}

Configuration for second Solr server

@Configuration
public class SecondarySolrContext {
  @Bean
  public SolrClient secondarySolrClient() {
    return new HttpSolrClient(...);
  }

  @Bean("secondary")
  public SolrTemplate solrTemplate() {
    return new SolrTemplate(secondarySolrClient());
  }
}

Using the SolrTemplates

@Service
public class SearchService {
  @Autowired
  @Qualifier("primary")
  private SolrTemplate primarySolrTemplate;

  @Autowired
  @Qualifier("secondary")
  private SolrTemplate secondarySolrTemplate;
}

之所以有效,是因为:

  1. 第一个SolrTemplate通过明确的方法调用(primarySolrClient())直接引用它的SolrClient
  2. 第二个SolrTemplate通过明确的方法调用(secondarySolrClient())直接引用它的SolrClient
  3. 第一个 SolrTemplate 明确命名为 (@Bean("primary"))。
  4. 第二个SolrTemplate也明确命名为(@Bean("secondary"))。
  5. SolrTemplates 通过 @Qualifier.
  6. 使用其唯一名称明确注入

可以以这种方式初始化和注入更多 SolrTemplate

示例项目可用on Github 演示了这一点。