Spring Solr - 将多个客户端用于不同的服务
Posted
技术标签:
【中文标题】Spring Solr - 将多个客户端用于不同的服务【英文标题】:Spring Solr - Using multiple clients to different services 【发布时间】:2017-06-07 22:18:22 【问题描述】:我正在使用一个聚合来自多个来源的数据的应用程序。在这种情况下,我需要使用不相关的数据连接到两个不同的 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。由于需要 solrClient() 和 solrTemplate() bean,并且尝试使用不同的 URL 创建新的 Context 只会让 solrClient 和 solrTemplate bean 被首先创建的 bean 覆盖。如果它们是唯一定义的 Solr 客户端,则每个客户端都可以正常工作。
简而言之,我如何创建两个(或更多)不同的 Spring Solr 客户端,每个客户端都连接到不同的 URL?
附加信息是对 cmets 的响应...
我试图简单地重新创建具有不同配置的 SolrContext 类。请考虑以下几点:
@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 的 solrClient 和 solrTemplate 在启动期间创建 bean 时被覆盖。
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 功能无法定位/识别 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(不仅仅是核心)?
【问题讨论】:
【参考方案1】:由于在同一个 Spring 上下文中有多个相同类型的 bean,因此在使用自动装配时需要消除歧义。以下应该有效:
第一个 Solr 服务器的配置
@Configuration
public class PrimarySolrContext
@Bean
public SolrClient primarySolrClient()
return new HttpSolrClient(...);
@Bean("primary")
public SolrTemplate solrTemplate()
return new SolrTemplate(primarySolrClient());
第二个 Solr 服务器的配置
@Configuration
public class SecondarySolrContext
@Bean
public SolrClient secondarySolrClient()
return new HttpSolrClient(...);
@Bean("secondary")
public SolrTemplate solrTemplate()
return new SolrTemplate(secondarySolrClient());
使用
SolrTemplate
s
@Service
public class SearchService
@Autowired
@Qualifier("primary")
private SolrTemplate primarySolrTemplate;
@Autowired
@Qualifier("secondary")
private SolrTemplate secondarySolrTemplate;
之所以有效,是因为:
-
第一个
SolrTemplate
直接通过明确的方法调用 (primarySolrClient()
) 引用其 SolrClient
。
第二个SolrTemplate
直接通过明确的方法调用(secondarySolrClient()
) 引用它的SolrClient
。
第一个 SolrTemplate
被明确命名为 (@Bean("primary")
)。
第二个SolrTemplate
也被明确命名为 (@Bean("secondary")
)。
SolrTemplate
s 通过 @Qualifier
使用其唯一名称明确注入。
更多SolrTemplate
s 可以用这种方式初始化和注入。
on Github 提供了一个示例项目来证明这一点。
【讨论】:
它不起作用,错误是 - 一个组件需要一个名为 'solrClient' 的 bean,但无法找到。【参考方案2】:为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);
【讨论】:
我已经做到了。它不起作用,因为 bean 被第一个实例覆盖。我需要的是指向不同的服务器,而不是核心。这是来自启动日志“用不同的定义覆盖 bean 'solrClient' 的 bean 定义:替换 ...” solrTemplate bean 有类似的消息。 它被 Spring 覆盖了吗? 是的。查看添加到问题中的其他 cmets。以上是关于Spring Solr - 将多个客户端用于不同的服务的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data Solr - 由 OR 分隔的多个 FilterQueries
Spring集成Solr 客户端,提示如下错误信息:java.lang.NoClassDefFoundError: org/apache/http/message/TokenParser