首页跳转到搜索页面及搜索实现分析、使用SolrJ查询索引库、搜索服务Dao实现、搜索功能Service实现、商品搜索功能Controller实现、搜索功能测试、使用SolrJ管理Solr集群、切换到集

首页跳转到搜索页面及搜索实现分析

上节课我们一起学习了将数据从数据库导入到索引库,这节课我们一起学习下首页跳转到搜索页面。

我们要访问taotao-portal-web工程就要先启动redis服务(大家根据自己使用的情况启动,使用的是单机版就启动单机版服务器,使用的是集群就启动集群版服务器)。

启动好taotao-portal-web工程之后,我们访问淘淘商城首页,如下图所示。

该首页对应的后台代码如下所示,在index.jsp当中是没有搜索相关代码的,那么这部分代码在哪儿呢?其实是在header.jsp当中。

header.jsp页面的代码如下图所示,可以看到在搜索框中输入搜索搜索关键词之后,点回车即可触发search方法。但我们发现在整个header.jsp当中并没有search方法,那么search方法在哪儿呢?其实是在页面引用的src="/js/base-v1.js"当中。

base-v1.js中有search这个方法,如下图所示,它指定的访问端口是8082,我们要把它改成8085,,因为8085对应着我们的taotao-search-web工程。

我们使用tomcat插件启动的方式启动taotao-search-web工程,启动方法是在工程上右键-------->Run As------->Maven Install,会看到如下图所示弹出框,在Goals一栏输入"clean tomcat7:run"。点击"Apply",然后点击"Run"就可以启动该工程了。

我们在淘淘商城首页的搜索框中输入"手机"然后点击搜索按钮,会看到如下图所示界面,可以看到已经正确跳转到搜索工程了,只是我们的搜索功能还没完成因此现在访问是报404的。

下面我们来分析一下搜索功能的实现,我们首先把搜索工程的静态资源,大家可以到http://download.csdn.net/detail/u012453843/9830293这个地址进行下载。下载解压之后放到搜索工程当中,如下图所示。

我们商品搜索页面只需进行查询和分页即可,我们现在不用像京东做的这么复杂,练习嘛,我们就不使用过滤条件、排序等功能了。我们只实现查询和分页功能。

我们再到search.jsp页面查看一下代码,可以看到搜索页面由总页数totalPages和搜索出来的内容列表itemList组成,而且可能会用到查询总数量。这些我们应该放到一个pojo当中。

由于搜索服务和搜索工程都需要用到这个pojo,因此我们还是把这个pojo放到taotao-common当中比较合适。如下图所示。注意类一定要实现序列化接口!!—SearchResult.java

使用SolrJ查询索引库

我们有必要在工程中写查询索引库的代码前先进行必要的测试。我们先到Solr服务页面去简单进行查询,如下图所示,在搜索条件"q"这一栏,我们输入"手机",分页参数的每页显示条数我们随便写一个数,这里我写的是3,也就是一次只查询三条数据,由于在查询条件一栏没有指定搜索域,因此默认搜索域一定要指定,否则无法查询出数据,我们在solr服务器的schema.xml文件当中配置了复制域"item_keywords",我们的默认搜索域便使用复制域"item_keywords"。我们知道在天猫或者京东,当搜索出结果后关键字是高亮显示的,我们也应该有高亮显示效果,我们点击"hl"前面的复选框就会展开如下图关于高亮显示的配置,让我们指定要高亮显示的字段以及高亮显示的html代码(在关键字前面和后面都有,比如手机)。点击"Execute Query"按钮便可以查询到如下图右侧的数据,上面是查询出来的商品列表信息,下面是高亮信息"highlighting"。

大家应该注意到下图高亮数据部分有一条查询结果是空的(“143771131488369”:{}),这是因为这条数据的item_title字段是"121"并没有关键字"手机",但是在商品分类中有"手机",于是认为该商品也符合搜索条件(复制域的意思是把各个字段的值都复制到"item_keywords"当中,查询的时候,只要满足其中一个字段的条件便认为是满足条件),但由于"item_title"字段没有"手机",因此显示的高亮结果是"143771131488369":{}

针对上面的查询条件,我们使用java测试代码来跑一遍,代码如下所示。queryDocumentPhone()

在这里插入图片描述
在这里插入图片描述

搜索服务Dao实现

我们先来看下上节课我们一起学习的solrj查询测试代码,如下图所示,可以看到,代码的上半部分是比较灵活的,根据用户查询条件的不同而不同,但是红色圈住的那部分代码则是固定的,不论什么查询条件都要执行下面那段代码,因此我们可以考虑将下面那段代码封装起来,写到Dao层。—就是查询、将查询结果封装的那些

我们根据在公司的实际操作场景来写,在实际开发中一般都是要有接口和实现类的,因此我们在taotao-search-interface工程新建一个com.taotao.search.dao包,并在该包下新建一个接口类SearchDao,如下图所示。

我们在taotao-search-service工程添加一个com.taotao.search.dao.impl包并在该包下新建SearchDao的实现类SearchDaoImpl,如下图所示。

这样,我们的Dao层便写完了。

搜索功能Service实现

首先我们在taotao-search-interface工程新建一个接口类SearchService,并在接口类中添加一个接口,如下图所示。

接着,我们到taotao-search-service工程添加一个实现类SearchServiceImpl,并实现SearchService接口,如下图所示。

在上面的实现类中使用注解的方式注入SearchDao,能不能注入成功呢?答案是不行的,因为我们在taotao-search-service的spring配置文件中配置的扫描包的范围是com.taotao.search.service,而com.taotao.search.dao不在这个范围内,从而无法将dao这个包下的接口类扫描到spring容器当中,我们也无法注入成功,解决方法有两种,第一种是把扫描包的范围扩大,由原来的com.taotao.search.service改为com.taotao.search,这样com.taotao.search.dao和com.taotao.search.service两个包就都可以被扫描进spring容器当中了。第二种方法是在已有的扫描包后面再加一个扫描范围com.taotao.search.dao,中间以","分隔(base-package=“com.taotao.search.service,com.taotao.search.dao”)。

写完了Service,下面我们便要发布服务,我们在taotao-search-service工程的applicationContext-service.xml文件中暴露搜索接口,如下图所示。

商品搜索功能Controller实现

在taotao-search-web工程需要添加对Search服务的引用,如下图所示。

下面我们写一个Controller,SearchController

下面对Controller当中代码做下解释并需要在配置文件配置下每页显示数量。
首先,@RequestMapping("/search")的值为何是"/search",这要从搜索页面代码说起,在search.jsp页面当中是没有搜索代码的,搜索代码在commons/header.jsp当中。

我们打开commons目录下的header.jsp页面,可以看到当我们在搜索框中输入搜索条件并按回车后会触发search方法,这个search方法并不在这个header.jsp当中,而是在引用的base-v1.js当中。

我们到base-v1.js当中,找到search方法,在search方法中,我们可以看到要访问的页面是search.html,我们的taotao-search-web工程拦截的就是以".html"结尾的文件,因此没有问题,既然要请求search.html,我们当然要拦截的是"search"了。另外,大家在这里也看到了,请求后面的参数是以"q"来携带的,这个变量名字与我们Controller当中定义的参数名称"queryString"不一致,名称不一致的情况需要指定映射关系,于是便有了@RequestParam(“q”) String queryString。

我们从上图的请求当中可以看到也没有每页显示多少条的参数,而这个参数必须是灵活可配置的,因此最好写到配置文件当中。如下图所示。

search方法中的Model参数是为了向页面回显数据用的,我们可以看下搜索页面都需要回显哪些数据,可以看到有四个值需要回显,这也刚好对应着我们在Controller类中所回显的四个变量。

方法最后返回逻辑视图"search"经过spring自动添加后缀.jsp,于是便去访问这个search.jsp页面,并把四个变量也都带过来了,这样,页面便可以正常显示数据了。

好了,至此,我们的Controller便完成了。

搜索功能测试

经过前面几节的学习,我们把搜索相关代码写完了,这节我们一起测试下搜索功能。

首先我们要保证zookeeper、redis、image、solr服务都开启。

接着,我们把taotao-common工程重新打包到本地maven仓库,然后把taotao-search工程也打包到本地maven仓库。

下面我们依次启动taotao-manager、taotao-content、taotao-search三个服务,然后启动taotao-manager-web、taotao-portal-web、taotao-search-web三个系统。

启动完之后,我们到淘淘商城首页,如下图所示,我们在搜索框中输入"手机"并按回车进行搜索。

搜索结果如下图,可以看到,搜索结果乱码了。

那么,我们怎么解决乱码问题呢?我们可以直接在Controller当中解决,如下图所示。工程默认的编码是"iso8859-1",现在需要把它修改为"utf-8"。

修改完之后,我们重启taotao-search-web工程,然后我们再在淘淘商城首页的搜索框中输入"手机"然后回车进行查询,便可以看到如下图所示界面,可以看到搜索出结果了,只是由于数据库中存储的图片地址都是测试数据,是无法访问的,因此都没有图片。

我们可以在淘淘商城后台添加一个关于手机的商品,如下图所示,输入完商品信息后点击"提交"。

我们到数据库最后一页,可以看到我们刚才添加的手机信息,如下图所示。

我们到搜索工程,在搜索框中输入"小米"然后回车即可搜索小米的商品,如下图所示,可以看到并没有我们刚才添加的手机,这是什么原因呢?其实很简单,是因为我们刚才添加的商品并没有在索引库中,因此我们需要把数据库中的商品与索引库重新同步一下。

我们到淘淘商城后台进行同步数据库数据到索引库,如下图所示。点击"导入数据到索引库。由于数据量较大,导入需要几十秒的时间。

导入成功后,我们再到搜索工程进行搜索,发现这时成功搜索出该手机了!

但是到这里依然会有个问题,我们在后台添加商品的时候可以指定多张图片,我们试下多张图片的情况下,还能不能正常搜索出带图片的手机。如下图所示,我们添加一款金立手机并上传了三张图片。

添加完金立M2017手机之后,我们还需要重新将数据库中的数据与索引库进行同步,这里就不啰嗦怎么操作了。同步之后,我们在搜索工程输入"金立M2017"然后回车进行搜索,发现搜索到了结果但是图片无法正常显示。如下图所示。

这是什么原因造成的呢?其实也很简单,我们看下数据库中存储的数据格式,我们刚添加的手机image字段存储的信息如下所示,可以看到是三张图片地址中间以","分隔拼成的字符串,这样的字符串在页面是无法正常显示的,我们需要把图片进行拆分,显示其中的一张才行。

http://192.168.156.13:8888/group1/M00/00/00/wKicDVkHzTiAVCl3AADZzN2RODM244.jpg,http://192.168.156.13:8888/group1/M00/00/00/wKicDVkHzTiAVZaFAABmf6hpOQM129.jpg,http://192.168.156.13:8888/group1/M00/00/00/wKicDVkHzTiAMvRzAAADTv6ZwbQ551.jpg

我们到SearchDaoImpl当中进行处理,如下图所示。
修改后的SearchDaoImpl.java类的代码如下

修改了taotao-search-service,我们便要重启taotao-search工程,重启之后,我们重新搜索"金立M2017"便可以看到图片了,如下图所示。

下面还有功能没有完善,那就是下一页、上一页,当我们点击上图的下一页时,会看到如下图所示界面,说明请求就不正确,因为它默认访问的端口是8082,而我们的搜索工程的端口是8085,因此我们需要找到控制下一页、上一页功能的js并做下修改。

我们在search.jsp页面当中可以看到引用了脚本search_main.js,这个js就控制了我们的上一页、下一页的操作。

我们打开search_main.js文件,在文件中搜索8082,只有一处,我们把8082,修改为8085,如下图所示。

下面我们到搜索工程再点击"下一页",会看到如下图所示界面,发现已经正常到第2页了,说明上一页、下一页功能也正常了!我们的搜索完成了!!!

总结:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行

错误1
2019-09-01 11:42:24,078 [http-bio-8085-exec-2] [org.springframework.web.servlet.PageNotFound]-[WARN] No mapping found for HTTP request with URI [/] in DispatcherServlet with name ‘taotao-search-web’

错误2
javax.el.PropertyNotFoundException: Property ‘images’ not found on type com.taotao.common.pojo.SearchItem

严重: Servlet.service() for servlet [taotao-search-web] in context with path [] threw exception [An exception occurred processing JSP page /WEB-INF/jsp/search.jsp at line 47

改为image属性

错误3
javax.el.PropertyNotFoundException: Property ‘0’ not found on type java.lang.String

严重: Servlet.service() for servlet [taotao-search-web] in context with path [] threw exception [An exception occurred processing JSP page /WEB-INF/jsp/search.jsp at line 47

改为image,因为这里我们只取得图片数组中的第一张展示出来

使用SolrJ管理Solr集群

首先,大家需要搭建Solr集群,关于Solr集群的搭建http://blog.csdn.net/u012453843/article/details/70767178这篇博客进行了非常详细的说明,大家可以参考搭建。

刚搭建好的Solr集群,是没有任何索引数据的,如下图所示。

下面我们新建一个测试类TestSolrCloud,然后写一个测试方法

搜索功能切换到集群

Solr单机版使用的是HttpSolrServer,集群版用的是CloudSolrServer,这两个类都是SolrServer的子类,我们在Dao层使用的SolrServer进行操作,从而我们可以不用改Dao层代码,只需要在Spring容器中切换单机版或集群版Solr即可。

现在我们到applicationContext-solr.xml文件当中配置一下Solr集群

由于还没有将数据库中的数据导入到集群版的索引库,因此我们需要到淘淘商城后台重新导入到索引库,不过在此之前,我们最好把上节课测试添加的那条数据给删除掉。如下图所示,我们点击"Documents",在Document Type类型中选择XML,在Document(s)中输入删除语句,然后点击提交按钮即可完成删除操作。

下面我们把数据库中的数据导入到集群版索引库(整个过程耗费的时间比较长,一两分钟左右),如下图所示。

导入成功后,我们访问淘淘商城首页,并在搜索框中输入"金立M2017"并按回车进行搜索,发现可以正常搜索到结果,如下图所示。说明我们切换到集群版后,代码完全没问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值