2019独角兽企业重金招聘Python工程师标准>>> hot3.png

关于Solr

Broadleaf项目中关于商品的搜索使用了嵌入式的Solr服务器,这个从配置文件中可以看出来。

  • 项目主页: http://www.broadleafcommerce.com/

  • 示例网站: http://demo.broadleafcommerce.org/

  • 示例网站源代码: https://github.com/BroadleafCommerce/DemoSite

从示例网站源代码的applicationContext.xml文件中可以看到关于solr的配置:

    <bean id="solrEmbedded" class="java.lang.String">    <constructor-arg value="solrhome"/>     </bean>    <bean id="blSearchService" class="org.broadleafcommerce.core.search.service.solr.SolrSearchServiceImpl"> <constructor-arg name="solrServer" ref="${solr.source}" /><constructor-arg name="reindexServer" ref="${solr.source.reindex}" />     </bean>      <bean id="rebuildIndexJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="blSearchService" />         <property name="targetMethod" value="rebuildIndex" />     </bean><bean id="rebuildIndexTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"><property name="jobDetail" ref="rebuildIndexJobDetail" />         <property name="startDelay" value="${solr.index.start.delay}" />         <property name="repeatInterval" value="${solr.index.repeat.interval}" />     </bean>     <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         <property name="triggers">             <list>                 <ref bean="rebuildIndexTrigger" />                 <!--<ref bean="purgeCartTrigger" />-->                 <!--<ref bean="purgeCustomerTrigger" />-->             </list>         </property>     </bean>

资源配置文件在common.properties:

web.defaultPageSize=15
web.maxPageSize=100
solr.source=solrEmbedded
solr.source.reindex=solrEmbedded
solr.index.start.delay=5000
solr.index.repeat.interval=3600000

从上可以看出使用的Solr是嵌入式服务,Solr配置文件(schema.xml和solrconfig.xml)在 https://github.com/BroadleafCommerce/DemoSite/tree/master/site/src/main/resources 目录下。

从源代码SolrSearchServiceImpl.java中可以看出,一共启动了两个Solr服务,分别对应primary和reindex两个solrcore,primary用于查询,reindex用于重建索引。

改进搜索引擎

改进目标

本篇文章只是将嵌入式Solr服务换成独立运行的Solr服务,你还可以更进一步换成SolrCloud集群。

  • 单独搭建搜素引擎服务器

  • 支持增量更新索引

  • 支持手动重建索引

设计思路

  • 1.修改原系统中的嵌入式搜索引擎为独立部署的搜索引擎,安装方法见下文。

  • 2.扩展原系统中的SolrSearchServiceImpl类,添加增加索引的方法。

  • 3.修改原来系统中商品的service类(我这里调用的是LLCatalogServiceImpl,该类是新添加的),在saveProduct方法中添加往搜索引擎添加索引的方法。

  • 4.修改原系统中solr相关的配置文件。

  • 5.修改原系统中的重建索引的定时任务,以支持手动重建索引。

实现方法

1、搭建独立运行的solr服务器

你可以参考:Apache Solr介绍及安装

关键在于solr/home的定义,以及在该目录下创建两个目录,分别为primary和reindex,两个目录下的配置文件都一样,solr/home目录结构如下:

➜  solrhome-solr  tree -L 3
.
├── primary │   └── conf │       ├── schema.xml │       └── solrconfig.xml
├── reindex │   └── conf │       ├── schema.xml │       └── solrconfig.xml └── solr.xml 4 directories, 5 files

solr.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="true">   <cores defaultCoreName="primary" adminPath="/admin/cores">     <core instanceDir="reindex" name="reindex"/>     <core instanceDir="primary" name="primary"/>   </cores>
</solr>

schema.xml内容和原来的基本一样,只是添加了一行:

<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>

solrconfig.xml内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<config>   <luceneMatchVersion>4.4</luceneMatchVersion>   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/><schemaFactory class="ClassicIndexSchemaFactory"/>   <updateHandler class="solr.DirectUpdateHandler2">     <autoCommit>         <maxDocs>2</maxDocs>         <maxTime>3000</maxTime>     </autoCommit>   </updateHandler>  <requestHandler name="/get" class="solr.RealTimeGetHandler">     <lst name="defaults">       <str name="omitHeader">true</str>     </lst>   </requestHandler>   <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />    <requestDispatcher handleSelect="true" >     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" formdataUploadLimitInKB="2048" />     <httpCaching never304="true" />  </requestDispatcher>   <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />   <requestHandler name="/analysis/field" startup="lazy" class="solr.FieldAnalysisRequestHandler" />   <requestHandler name="/update" class="solr.UpdateRequestHandler"  />   <requestHandler name="/update/csv" class="solr.CSVRequestHandler" startup="lazy" />   <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler" startup="lazy" />   <requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />   <requestHandler name="/admin/ping" class="solr.PingRequestHandler">     <lst name="invariants">       <str name="q">solrpingquery</str>     </lst>     <lst name="defaults">       <str name="echoParams">all</str>     </lst>   </requestHandler>   <queryResponseWriter name="json" class="solr.JSONResponseWriter">         <str name="content-type">text/plain; charset=UTF-8</str>   </queryResponseWriter>  <!-- config for the admin interface -->    <admin>     <defaultQuery>solr</defaultQuery>   </admin>
</config>

2、扩展SolrSearchServiceImpl类

在core模块创建org.broadleafcommerce.core.search.service.solr.ExtSolrSearchService接口,该接口定义如下:

package org.broadleafcommerce.core.search.service.solr;
import java.io.IOException;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.core.catalog.domain.Product;
import org.broadleafcommerce.core.search.service.SearchService; public interface ExtSolrSearchService extends SearchService {     public void addProductIndex(Product product) throws ServiceException,     IOException; }

然后,创建其实现类org.broadleafcommerce.core.search.service.solr.ExtSolrSearchServiceImpl,该实现类定义如下:

package org.broadleafcommerce.core.search.service.solr;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Resource;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.common.locale.domain.Locale;
import org.broadleafcommerce.common.util.StopWatch;
import org.broadleafcommerce.common.util.TransactionUtils;
import org.broadleafcommerce.core.catalog.domain.Product;
import org.broadleafcommerce.core.search.domain.Field;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.xml.sax.SAXException; public class ExtSolrSearchServiceImpl extends SolrSearchServiceImpl implements         ExtSolrSearchService {     private static final Log LOG = LogFactory             .getLog(ExtSolrSearchServiceImpl.class);     @Resource(name = "blSolrIndexService")     protected SolrIndexServiceImpl solrIndexServiceImpl;     public ExtSolrSearchServiceImpl(SolrServer solrServer,SolrServer reindexServer) {super(solrServer, reindexServer);}public ExtSolrSearchServiceImpl(SolrServer solrServer) {super(solrServer);}public ExtSolrSearchServiceImpl(String solrServer, String reindexServer)throws IOException, ParserConfigurationException, SAXException {super(solrServer, reindexServer);}public ExtSolrSearchServiceImpl(String solrServer) throws IOException,ParserConfigurationException, SAXException {super(solrServer);}public void addProductIndex(Product product) throws ServiceException,IOException {TransactionStatus status = TransactionUtils.createTransaction("saveProduct", TransactionDefinition.PROPAGATION_REQUIRED,solrIndexServiceImpl.transactionManager, true);StopWatch s = new StopWatch();try {List<Field> fields = fieldDao.readAllProductFields();List<Locale> locales = solrIndexServiceImpl.getAllLocales();SolrInputDocument document = solrIndexServiceImpl.buildDocument(product, fields, locales);if (LOG.isTraceEnabled()) {LOG.trace(document);} SolrContext.getServer().add(document);SolrContext.getServer().commit();TransactionUtils.finalizeTransaction(status,solrIndexServiceImpl.transactionManager, false);} catch (SolrServerException e) {TransactionUtils.finalizeTransaction(status,solrIndexServiceImpl.transactionManager, true); throw new ServiceException("Could not rebuild index", e);} catch (IOException e) {TransactionUtils.finalizeTransaction(status,solrIndexServiceImpl.transactionManager, true);throw new ServiceException("Could not rebuild index", e); } catch (RuntimeException e) {TransactionUtils.finalizeTransaction(status,solrIndexServiceImpl.transactionManager, true);throw e;}LOG.info(String.format("Finished adding index in %s", s.toLapString()));}    protected List<Product> getProducts(QueryResponse response) {final List<Long> productIds = new ArrayList<Long>();SolrDocumentList docs = response.getResults();for (SolrDocument doc : docs) {productIds                     .add((Long) doc.getFieldValue(shs.getProductIdFieldName()));}/**          * TODO 请添加缓存相关代码          */ List<Product> products = productDao.readProductsByIds(productIds);// We have to sort the products list by the order of the productIds list// to maintain sortability in the UIif (products != null) { Collections.sort(products, new Comparator<Product>() {public int compare(Product o1, Product o2) {return new Integer(productIds.indexOf(o1.getId())).compareTo(productIds.indexOf(o2.getId())); }});}return products;}}

3、 修改solr相关配置文件

a. 删除web模块中/web/src/main/webapp/WEB-INF/applicationContext.xml的以下代码:

<bean id="blSearchService" class="org.broadleafcommerce.core.search.service.solr.SolrSearchServiceImpl"><constructor-arg name="solrServer" ref="${solr.source}" /><constructor-arg name="reindexServer" ref="${solr.source.reindex}" /></bean>

b.删除web模块中web/src/main/resources/runtime-properties/common.properties的以下代码:

solr.source=solrEmbedded
solr.source.reindex=solrEmbedded

c. 在core模块中core/src/main/resources/applicationContext.xml添加如下代码:

<bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer"> <constructor-arg value="${solr.url}" />
</bean><bean id="solrReindexServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer"> <constructor-arg value="${solr.url.reindex}" />
</bean> <bean id="blSearchService"     class="org.broadleafcommerce.core.search.service.solr.ExtSolrSearchServiceImpl">     <constructor-arg name="solrServer" ref="${solr.source}" />     <constructor-arg name="reindexServer" ref="${solr.source.reindex}" />
</bean>

d. 在core模块中core/src/main/resources/runtime-properties/common-shared.properties添加如下代码:

solr.url=
solr.url.reindex=http://localhost:8080/solr/reindex
solr.source=solrServer
solr.source.reindex=solrReindexServer

4、 修改LLCatalogServiceImpl类

添加如下代码:

@Resource(name = "blSearchService")
private ExtSolrSearchService extSolrSearchService;

修改该类的saveProduct方法如下:

@Override
@Transactional("blTransactionManager")
public Product saveProduct(Product product) {Product dbProduct = catalogService.saveProduct(product);     try {         extSolrSearchService.addProductIndex(dbProduct);     } catch (ServiceException e) {e.printStackTrace();throw new RuntimeException(e);     } catch (IOException e) {         e.printStackTrace();         throw new RuntimeException(e);     }     return dbProduct;}

5、 修改定时任务

a. web系统启动时候,会查询数据库中商品,然后重建索引。该功能在applicationContext.xml中已经定义了定时任务,建议取消该定时任务。去掉以下代码:

<bean id="rebuildIndexJobDetail"     class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="blSearchService" />     <property name="targetMethod" value="rebuildIndex" />
</bean> <bean id="rebuildIndexTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">     <property name="jobDetail" ref="rebuildIndexJobDetail" />     <property name="startDelay" value="${solr.index.start.delay}" />     <property name="repeatInterval" value="${solr.index.repeat.interval}" />
</bean><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list>             <ref bean="rebuildIndexTrigger" />         </list>     </property>
</bean>

b. 编写main方法,打成jar包,然后编写shell脚本,用于手动重建索引或者设置定时任务。该类需要获取一个名称为blSearchService的bean,然后调用该bean的rebuildIndex方法,主要代码如下。

@Resource(name = "blSearchService")
private SearchService extSolrSearchService;public void doRebuild(){ extSolrSearchService.rebuildIndex(); }

转载于:https://my.oschina.net/bluesummer/blog/312086

BroadLeaf项目搜索功能改进相关推荐

  1. java 搜索框快速查询_Java项目搜索功能的实现

    今天是刘小爱自学Java的第110天. 感谢你的观看,谢谢你. 话不多说,开始今天的学习: 事先说明:关于今天的搜索功能实现. 并没有使用到倒排索引这样的主流搜索技术,就一个普通的模糊查询. 在此之前 ...

  2. JSD-2204-(业务逻辑开发)-更新订单状态的功能-搜索功能-Quartz-Day12

    1.开发更新订单状态的功能 1.1订单的状态码 我们电商上面订单的状态修改是非常普通的业务 随着商品的购买流程,订单的状态有 状态: 0=未支付 1=已关闭(超时未支付) 2=已取消 3=已支付 4= ...

  3. java 搜索业务怎么写_Java项目实战第11天:搜索功能的实现

    原标题:Java项目实战第11天:搜索功能的实现 今天是刘小爱自学Java的第110天. 感谢你的观看,谢谢你. 话不多说,开始今天的学习: 事先说明:关于今天的搜索功能实现. 并没有使用到倒排索引这 ...

  4. vue项目搜索历史功能的实现

    vue项目搜索历史功能的实现 播放器项目中歌曲搜素页面的 首先需要在state定义搜索历史,在其中保存搜索历史 state.js:<br>// 搜索历史: searchHistory: [ ...

  5. Vue项目中利用pdf.js实现pdf内容滑选文字展示与搜索功能

    Vue项目中利用pdf.js实现pdf内容滑选文字展示与搜索功能 需求:在pdf中鼠标滑动选中一段文字,将选中文字展示到input框中(pdf在iframe中) 完成效果: 关于pdf的引用:我是直接 ...

  6. 项目需求讨论-标题栏上的搜索功能

    今天讲的就是一个很简单的具体开始时候遇到的需求,在标题栏中实现搜索功能,而且美工要求需要实现下面GIF图的效果,我就实现了下,可能不是最好的,有哪里可以更方便请大家指出.正好仔细的讲解了下Search ...

  7. 【ElasticSearch和whoosh实现项目中搜索功能】

    文章目录 说明: 一.单表搜索 二,全局搜索 方式一:haystack+whoosh+Jieba 方式二:haystack+ES 总结: 说明: 我们的项目中经常会遇到搜索的功能,最近也写过搜索的功能 ...

  8. vue项目中使用百度地图api完成自定义搜索功能(包含搜索详细地理位置)

    需求描述: 在vue项目中,有时候,我们需要自定义百度地图的一些功能.譬如,现在的需求,就是需要自定义搜索内容和结果展示. 类似如下页面的功能: 首先在vue项目中,我们可以使用 vue-baidu- ...

  9. 商城项目实战31:solar服务器搭建、搜索功能实现

    1. 需要做的事情 l Solr服务的搭建 l 搜索功能的实现 1.1. 系统架构 2. Solr概述 2.1. 什么是Solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基 ...

最新文章

  1. 泛型实体类List绑定到repeater
  2. 15 位学神争霸!2019 清华本科生特奖答辩入围名单公布
  3. 车辆2D/3D--Deep MANTA: A Coarse-to-fine Many-Task Network for joint 2D and 3D vehicle analysis
  4. Java IO流总结(zz)
  5. 学python找工作好找吗-前辈经历告诉你Python新手好找工作吗?初级岗位多不多
  6. Android序列化与反序列化
  7. 黑色星期日+一.....
  8. 二十、App爬虫环境搭建并测试监听微信
  9. 二分查找法---java实现
  10. html 自动滚动标签,HTML滚动标签(marquee标签)
  11. SQL语言:嵌入式SQL知识笔记
  12. vue-cli2、vue-cli3脚手架详细讲解
  13. @程序员,如何在编程面试中脱颖而出?
  14. nginx实现 二级目录跳转 子目录跳转
  15. Jmeter4.0新版本特性研究
  16. 好看的php表格样式,HTML5制作表格样式
  17. linux命令 dstat,dstat命令
  18. instead of触发器
  19. 斯坦福的《机器学习》课程上线了
  20. 客户端和服务器之间的信息结构,客户端与服务器之间的通信过程

热门文章

  1. cassss服务未启动_不要再本地启动项目调试了,试SpringBoot远程调试你会发现新大陆!...
  2. w ndows10电脑配置看哪里,win10对电脑配置要求及如何查看电脑配置
  3. java 对象排重_现代化的 Java (八)——重说对象序列化
  4. python fortran混合编程_python fortran c 混合编程
  5. trackbar控件显示刻度值_安卓自定义电平流图形控件
  6. abaqus python二次开发攻略_Python 进行 Abaqus 二次开发的基础知识
  7. 自考那些事儿(八):计算机网络原理(原理篇)之网络各层
  8. 保卫Google!刻不容缓
  9. 融完5亿美元创始人出局?腾讯投资的明星无人车公司Zoox地震了
  10. 砸115亿元入局!后知后觉的欧洲重金建设AI,为赶中超美