1.   学习计划

1、Solr服务搭建

2、Solrj使用测试

3、把数据库中的数据导入索引库

4、搜索功能的实现

2.   Solr服务搭建

2.1. Solr的环境

Solr是java开发。

需要安装jdk。

安装环境Linux。

需要安装Tomcat。

2.2. 搭建步骤

第一步:把solr 的压缩包上传到Linux系统

第二步:解压solr。

第三步:安装Tomcat,解压缩即可,然后复制一个到/usr/local/solr下面。

[root@localhost //]# mkdir /usr/local/solr

[root@localhost heima]# cp -rf apache-tomcat-7 /usr/local/solr

第四步:把solr部署到Tomcat的webapps下。

第五步:启动Tomcat会自动解压缩war包。

第六步:把/heima/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。

[root@localhost ext]# cp * /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/

第七步:创建一个solrhome。/example/solr目录就是一个solrhome。复制此目录到/usr/local/solr/solrhome

[root@localhost example]# cp -r solr /usr/local/solr/solrhome

第八步:关联solr及solrhome。需要修改solr工程的web.xml文件。

第九步:启动Tomcat

访问显示以下界面即表示solr安装成功

2.3. 配置业务域

schema.xml中定义

1、商品Id

2、商品标题

3、商品卖点

4、商品价格

5、商品图片

6、分类名称

创建步骤:

第一步:把中文分析器添加到工程中。

1、把IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下

2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。

第二步:配置一个FieldType,制定使用IKAnalyzer

修改schema.xml文件

修改Solr的schema.xml文件,添加FieldType:

<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

第三步:配置业务域,type制定使用自定义的FieldType。

设置业务系统Field

<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
<field name="item_price" type="long" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category_name" type="string" indexed="true" stored="true" /> <field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_sell_point" dest="item_keywords"/>
<copyField source="item_category_name" dest="item_keywords"/>

第四步:重启tomcat

3.   搜索工程搭建

要实现搜索功能,需要搭建solr服务、搜索服务工程、搜索系统

搜索服务工程搭建

可以参考e3-manager创建。

e3-search(聚合工程pom)

|--e3-search-interface(jar)

|--e3-search-Service(war)

e3-search-web(war)

查东西不需要事务,所以不需要applicationContext-trans.xml

4.   使用solrJ管理索引库

使用SolrJ可以实现索引库的增删改查操作。

4.1.添加文档

第一步:把solrJ的jar包添加到工程中。

    <!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>

第二步:创建一个SolrServer,使用HttpSolrServer创建对象。

第三步:创建一个文档对象SolrInputDocument对象。

第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。

第五步:把文档添加到索引库中。

第六步:提交。

@Test
public void addDocument() throws Exception {
// 第一步:把solrJ的jar包添加到工程中。
// 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8090/solr");
// 第三步:创建一个文档对象SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
// 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
document.addField("id", "1");
document.addField("item_title", "测试商品");
document.addField("item_price", "199");
// 第五步:把文档添加到索引库中。
solrServer.add(document);
// 第六步:提交。
solrServer.commit();
}

4.2.删除文档

4.2.1.    根据id删除

第一步:创建一个SolrServer对象。

第二步:调用SolrServer对象的根据id删除的方法。

第三步:提交。

    @Test
public void deleteDocumentById() throws Exception {
// 第一步:创建一个SolrServer对象。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8090/solr");
// 第二步:调用SolrServer对象的根据id删除的方法。
//solrServer.deleteById("1");
solrServer.deleteById("id:1");
// 第三步:提交。
solrServer.commit();
}

5.   把商品数据导入到索引库中

5.1.Dao层

5.1.1.    Sql语句

SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b.`name` category_name
FROM
`tb_item` a
LEFT JOIN tb_item_cat b ON a.cid = b.id
WHERE a.`status`=1;

需要自己创建Mapper文件。

5.1.2.    创建对应数据集的pojo

public class SearchItem implements Serializable{
private String id;
private String title;
private String sell_point;
private long price;
private String image;
private String category_name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSell_point() {
return sell_point;
}
public void setSell_point(String sell_point) {
this.sell_point = sell_point;
}
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getCategory_name() {
return category_name;
}
public void setCategory_name(String category_name) {
this.category_name = category_name;
} public String[] getImages() {
if (image != null && !"".equals(image)) {
String[] strings = image.split(",");
return strings;
}
return null;
} }

5.1.3.    接口定义

public interface ItemMapper {

    List<SearchItem> getItemList();
}

5.1.4.    Mapper映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.e3mall.search.mapper.ItemMapper" > <select id="getItemList" resultType="cn.e3mall.common.pojo.SearchItem">
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b.`name` category_name
FROM
`tb_item` a
LEFT JOIN tb_item_cat b ON a.cid = b.id
WHERE a.`status`=1
</select>
</mapper>

5.2.Service层

5.2.1.    功能分析

1、查询所有商品数据。

2、循环把商品数据添加到索引库。使用solrJ实现。

3、返回成功。返回E3Result

参数:无

返回值:E3Result

5.2.2.    solrJ添加索引库

1、把solrJ的jar包添加到工程。

2、创建一个SolrServer对象。创建一个和sorl服务的连接。HttpSolrServer。

3、创建一个文档对象。SolrInputDocument。

4、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。

5、把文档添加到索引库

6、Commit。

5.2.3.    代码实现

@Service
public class SearchServiceImpl implements SearchService{ @Autowired
private ItemMapper itemMapper;
@Autowired
private SolrServer solrServer; @Override
public E3Result importItemAlls() {
try {
//查询商品列表
List<SearchItem> itemList = itemMapper.getItemList();
//导入索引库
for (SearchItem searchItem : itemList) {
//创建文档对象
SolrInputDocument document = new SolrInputDocument();
//向文档中添加域
document.addField("id", searchItem.getId());
document.addField("item_title", searchItem.getTitle());
document.addField("item_sell_point", searchItem.getSell_point());
document.addField("item_price", searchItem.getPrice());
document.addField("item_image", searchItem.getImage());
document.addField("item_category_name", searchItem.getCategory_name());
//写入索引库
solrServer.add(document);
}
//提交
solrServer.commit();
//返回成功
return E3Result.ok(); } catch (Exception e) {
e.printStackTrace();
return E3Result.build(500, "商品导入失败");
}
} }

5.2.4.    applicationContext-solr.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg index="0" value="http://192.168.25.128:8090/solr"/>
</bean> </beans>

5.2.5.    发布服务

applicationContext-service.xml

5.3. 表现层

在e3-manager-web中导入searchService包

后台管理工程中调用商品导入服务。

    <dubbo:reference interface="cn.e3mall.search.service.SearchService" id="searchServiceImpl" />

5.3.1.    功能分析

请求的url:/index/item/import

响应的结果:json数据。可以使用E3Result

5.3.2.    Controller

@Controller
public class SearchItemController {
@Autowired
private SearchService searchItemService; @RequestMapping("/index/item/import")
@ResponseBody
public E3Result impotItemIndex() {
E3Result result = searchItemService.importItemAlls();
return result;
} }

5.4. 解决Mapper映射文件不存在异常

 <!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

6.   搜索功能实现

6.1. 使用sorlJ 查询索引库

//使用solrJ实现查询
@Test
public void queryDocument() throws Exception {
//创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8090/solr");
//创建一个查询对象,可以参考solr的后台的查询功能设置条件
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery("阿尔卡特");
// query.set("q","阿尔卡特");
//设置分页条件
query.setStart(1);
query.setRows(2);
//开启高亮
query.setHighlight(true);
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
//设置默认搜索域
query.set("df", "item_title");
//执行查询,得到一个QueryResponse对象。
QueryResponse queryResponse = solrServer.query(query);
//取查询结果总记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("查询结果总记录数:" + solrDocumentList.getNumFound());
//取查询结果
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮后的结果
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title= "";
if (list != null && list.size() > 0) {
//取高亮后的结果
title = list.get(0);
} else {
title = (String) solrDocument.get("item_title");
}
System.out.println(title);
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
} }

6.2. 功能分析

把搜索结果页面添加到工程中。

请求的url:/search

请求的方法:GET

参数:

keyword:查询条件

Page:页码。如果没有此参数,需要给默认值1。

返回的结果:

1)商品列表

2)总页数

3)总记录数

使用jsp展示,返回逻辑视图。

商品列表使用:SearchItem表示。

需要把查询结果封装到一个pojo中:

1)商品列表List<SearchItem>

2)总页数。Int totalPages。总记录数/每页显示的记录数向上取整。把每页显示的记录是配置到属性文件中。

3)总记录数。Int recourdCount

public class SearchResult implements Serializable {
private List<SearchItem> itemList;
private int totalPages;
private int recourdCount;
}

6.3. Dao层

跟据查询条件查询索引库,返回对应的结果。

参数:SolrQuery

返回结果:SearchResult

@Repository
public class SearchDao { @Autowired
private SolrServer solrServer; public SearchResult search(SolrQuery query) throws Exception {
//根据查询条件查询索引库
QueryResponse queryResponse = solrServer.query(query);
//取查询结果总记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
long numFound = solrDocumentList.getNumFound();
//创建一个返回结果对象
SearchResult result = new SearchResult();
result.setRecourdCount((int) numFound);
//创建一个商品列表对象
List<SearchItem> itemList = new ArrayList<>();
//取商品列表
//取高亮后的结果
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
//取商品信息
SearchItem searchItem = new SearchItem();
searchItem.setCategory_name((String) solrDocument.get("item_category_name"));
searchItem.setId((String) solrDocument.get("id"));
searchItem.setImage((String) solrDocument.get("item_image"));
searchItem.setPrice((long) solrDocument.get("item_price"));
searchItem.setSell_point((String) solrDocument.get("item_sell_point"));
//取高亮结果
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String itemTitle = "";
if (list != null && list.size() > 0) {
itemTitle = list.get(0);
} else {
itemTitle = (String) solrDocument.get("item_title");
}
searchItem.setTitle(itemTitle);
//添加到商品列表
itemList.add(searchItem);
}
//把列表添加到返回结果对象中
result.setItemList(itemList);
return result;
}
}

6.4. Service层

需要有一个接口一个实现类,需要对外发布服务。

参数:String keyWord

int page

int rows

返回值:SearchResult

业务逻辑:

1)根据参数创建一个查询条件对象。需要指定默认搜索域,还需要配置高亮显示。

2)调用dao查询。得到一个SearchResult对象

3)计算查询总页数,每页显示记录数就是rows参数。

@Autowired
private SearchDao searchDao; @Override
public SearchResult search(String keyWord, int page, int rows) throws Exception {
//创建一个SolrQuery对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery(keyWord);
//设置分页条件
query.setStart((page - 1) * rows);
//设置rows
query.setRows(rows);
//设置默认搜索域
query.set("df", "item_title");
//设置高亮显示
query.setHighlight(true);
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em style=\"color:red\">");
query.setHighlightSimplePost("</em>");
//执行查询
SearchResult searchResult = searchDao.search(query);
//计算总页数
int recourdCount = searchResult.getRecourdCount();
int pages = recourdCount / rows;
if (recourdCount % rows > 0) pages++;
//设置到返回结果
searchResult.setTotalPages(pages);
return searchResult;
}

发布服务

6.5. 表现层

6.5.1.    引用服务

在e3-search-web中添加接口依赖

Springmvc.xml

<dubbo:reference interface="cn.e3mall.search.service.SearchService" id="searchService" />

6.5.2.    Controller

请求的url:/search

请求的方法:GET

参数:

keyword:查询条件

Page:页码。如果没有此参数,需要给默认值1。

返回的结果:

使用jsp展示,返回逻辑视图。

@Controller
public class SearchController { @Autowired
private SearchService searchService; @Value("${PAGE_ROWS}")
private Integer PAGE_ROWS; @RequestMapping("/search")
public String search(String keyword,@RequestParam(defaultValue="1") Integer page, Model model) throws Exception {
//需要转码
keyword = new String(keyword.getBytes("iso8859-1"), "utf-8");
//调用Service查询商品信息
SearchResult result = searchService.search(keyword, page, PAGE_ROWS);
//把结果传递给jsp页面
model.addAttribute("query", keyword);
model.addAttribute("totalPages", result.getTotalPages());
model.addAttribute("recourdCount", result.getRecourdCount());
model.addAttribute("page", page);
model.addAttribute("itemList", result.getItemList());
//返回逻辑视图
return "search";
} }

6.6.页面效果

在搜索框中,输入要买的手机

总结

问题:org.springframework.beans.factory.NoSuchBeanDefinitionException

解决:mapper扫描没有配置好,我们的mapper有多个路劲!

问题:Waiting server-side response timeout.

解决:发布服务时,记得加上timeout="600000",不然采取的是默认的1000毫秒

<dubbo:service interface="cn.e3mall.search.service.SearchService" ref="searchServiceImpl"  timeout="600000"/>

SSM商城项目(七)的更多相关文章

  1. SSM商城项目(二)

    1. 学习计划 1.将工程改造为基于SOA架构 2.商品列表查询功能实现. 2. 将工程改造为SOA架构 2.1. 分析 由于商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询 ...

  2. SSM商城项目(一)

    1. 学习计划 1.电商行业的背景. 2.宜立方商城介绍 3.宜立方商城的系统架构 a) 功能介绍 b) 架构讲解 4.工程搭建-后台工程 a) 使用maven搭建工程 b) 使用maven的tomc ...

  3. SSM商城项目(四)

    1. 学习计划 1.图片服务器 2.图片服务器安装 3.图片服务器的使用 4.图片上传功能 5.富文本编辑器的使用方法 6.商品添加功能实现 2. 图片服务器 1.存储空间可扩展. 2.提供一个统一的 ...

  4. SSM商城项目(十)

    1.   学习计划 1.使用freemarker实现网页静态化 a)Freemarker的使用方法 b)Freemarker模板的语法 c)Freemarker整合springmvc 2.Active ...

  5. SSM商城项目(八)

    1.   学习计划 1.solr集群搭建 2.使用solrj管理solr集群 3.把搜索功能切换到集群版 4.添加商品同步到索引库 2.   什么是SolrCloud SolrCloud(solr 云 ...

  6. SSM商城项目(五)

    1.   学习计划 1.前台系统搭建 2.商城首页展示 3.Cms系统的实现 a)         内容分类管理 b)         内容管理 4.前台内容动态展示 2.   商城首页展示 2.1. ...

  7. SSM商城项目(十三)

    1.   学习计划 1.订单系统 2.提交订单 3.MyCAT 2.   订单系统 2.1. 功能分析 1.在购物车页面点击“去结算”按钮跳转到订单确认页面. a)         展示商品列表 b) ...

  8. SSM商城项目(十二)

    1.   学习计划 1.购物车实现 2.未登录状态下使用购物车 3.登录状态下使用购物车 2.   购物车的实现 2.1. 功能分析 1.购物车是一个独立的表现层工程. 2.添加购物车不要求登录.可以 ...

  9. SSM商城项目(十一)

    1.   学习计划 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 Ajax跨域请求(jsonp) 2.   Sso系统工程搭建 需要创建一个sso服务工程,可以参考e ...

随机推荐

  1. Python多进程并发操作中进程池Pool的应用

    Pool类 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量的时间.如果操作的对象数目不大时,还可以直接使用Process类动态的生成多个进程,十 ...

  2. window.location.href webkit不兼容

    window.event.returnValue=false; 在location.href后加上后修复 来自为知笔记(Wiz)

  3. leetcode 152. Maximum Product Subarry

    这道题求的是乘积的最大值的,那么依照之前的和的最大值类似的做法的,乘积的最大值可能是在最大值*当前值和最小值*当前值和当前值三者之间取得的最大值的,那么使用两个变量来保存每一步的最大最小值的. cla ...

  4. prototype的一些事

    <script type="text/javascript"> foo=function(){ this.mayName="Foo function" ...

  5. psql的安装与数据库创建(ubuntu)

    来自阮一峰日志 http://www.ruanyifeng.com/blog/2013/12/getting_started_with_postgresql --------------------- ...

  6. spring--多人开发,模块化配置

    需要在配置文件中配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h ...

  7. mingw using pthread

    转载http://www.cnblogs.com/tfanalysis/p/5505163.html ftp://sourceware.org/pub/pthreads-win32/ 有的时候需要使用 ...

  8. find查找文件的时间问题

    很多细节方面的东西没有到真正用的时候,是觉察不出来的,因为这个时间的问题出了问题,现在好好理一下,这个find的时间很容易就搞混了,一段时间不用,也忘了,也反映出来了自己的基础知识不是很牢固啊   f ...

  9. webpack 中,module、chunk、bundle 的区别(待补充)

    项目 区别 module 是开发中的单个模块 chunk 中文意思是"块",是指 webpack 在进行模块依赖分析的时候,代码分割出来的代码块 bundle

  10. Delphi2009之TImage

    TPngImage原来是SourceFroge上的一个开源项目,现在突然消失了,为什么呢?Nick 在他的博客上写到:TPNGImage被CodeGear/Embarcadero收购了,现在直接就是D ...