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. MarkDown学习——基础用法

    目录 MarkDown开发版本MD2All基础用法 此处有代码<a id="top"></a>作为页内锚点 此处是用自动生成的目录 MarkDown是什么M ...

  2. ArcSDE账户频繁被锁定(Oracle显示12560协议适配器错误)

    最近遇到了一个比较奇葩的问题,启动系统的时候无法显示地图服务,查找原因时发现无法连接Oracle.出现以下错误: 之前遇到这种问题,通常是由于同时安装了64位和32位Oracle客户端,且二者的环境变 ...

  3. python要开始记录了20181125

    print('1.使用while循环输入 1 2 3 4 5 6 8 9 10') i = 1 while i < 10: i += 1 if i == 7: continue #print(' ...

  4. MySQL8.0 关闭二进制日志

    Binary logging is enabled by default (the log_bin system variable is set to ON). The exception is if ...

  5. PythonStudy——python中如何使输出不换行

    1.在python 3.x版本中,使用print(,end="") 可使输出不换行,  例如:

  6. centos7生产环境下openssh升级

    由于生产环境ssh版本太低,导致使用安全软件扫描时提示系统处于异常不安全的状态,主要原因是ssh漏洞.推荐通过升级ssh版本修复漏洞 因为是生产环境,所以有很多问题需要注意.为了保险起见,在生产环境下 ...

  7. 第二章 JavaScript案例(中)

    1. js事件 HTML代码 <!DOCTYPE html> <html lang="en" onUnload="ud()"> < ...

  8. 整数的故事(4)——Karastuba算法

    我们在小学就学过用竖式计算两个多位数的乘法: 这个过程简单而繁琐,没有最强大脑的普通大众通常是用计算器代替的.然而对于超大整数的乘法,计算器也未必靠得住,它还存在“溢出”一说.这就需要我们自行编写算法 ...

  9. ThreadLocal的学习

    一 用法ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量.1.Threa ...

  10. win10下btcd的安装和简单配置

    btcd btcd github地址 1. 安装 1) 安装go的包管理工具glide glide github地址 $ go get -u github.com/Masterminds/glide ...