1.   课程计划

1、搜索工程的搭建

2、linux下solr服务的搭建

3、Solrj使用测试

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

5、搜索功能的实现

2.   搜索工程搭建

要实现搜索功能,需要搭建solr服务、搜索服务工程、搜索系统(表现层的工程)

2.1. Solr服务搭建

2.1.1.    Solr的环境

  Solr是java开发。

  solr的安装文件需要安装jdk。

  安装环境Linux。

  需要安装Tomcat。

2.1.2.    搭建步骤

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

      Alt+p打开sftp窗口:输入put "F:/java/ziyuan/solr-4.10.3.tgz.tgz"

  第二步:解压solr :tar -xvf solr-4.10.3.tgz.tgz

      新建一个目录安装solr: cd /usr/local     --->     mkdir solr

  第三步:安装Tomcat,解压缩即可。

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

      将tomcat拷贝到solr目录下:cp apache-tomcat-7.0.52 /usr/local/solr -r

  第五步:解压缩war包。可以启动Tomcat解压。

      war包所在位置:solr-4.10.3/example/webapps/solr.war

      将该war包拷贝到:cp  solr.war /usr/local/solr/apache-tomcat-7.0.52/webapps

      启动Tomcat解压:

          cd /usr/local/solr/apache-tomcat-7.0.52/bin/

          ./startup.sh

          ./shutdown.sh

          ../webapps

          rm -rf solr.war  (删除掉这个war文件)         

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

    [root@localhost webapps]# cp /root/solr-4.10.3/example/lib/ext/*.jar /usr/local/solr/apache-tomcat-7.0.52/webapps/solr/WEB-INF/lib

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

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

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

    cd /usr/local/solr/apache-tomcat-7.0.52/webapps/solr/WEB-INF/

    修改web.xml文件: vim web.xml :

    

  第九步:启动Tomcat:

    cd /usr/local/solr/apache-tomcat-7.0.52/bin/

    ./startup.sh

    查看输出:

      

    网页测试:http://192.168.25.131:8080/solr/

  和windows下的配置完全一样。

2.1.3.    Solr的使用

  添加文档必须有id域,其他域 必须在solr的schema.xml中定义。

2.2. 配置业务域

schema.xml中定义

  1、商品Id      使用schema.xml中的id域

  2、商品标题

  3、商品卖点

  4、商品价格

  5、商品图片

  6、分类名称

  7、商品描述

创建对应的业务域。需要制定中文分析器。创建步骤:

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

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

     [root@localhost IKAnalyzer]# cp IKAnalyzer2012FF_u1.jar /usr/local/solr/apache-tomcat-7.0.52/webapps/solr/WEB-INF/lib

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

        cd /usr/local/solr/apache-tomcat-7.0.52/webapps/solr/WEB-INF

     [root@localhost WEB-INF]# mkdir classes

     [root@localhost WEB-INF]# cp /root/IKAnalyzer/*.dic *.xml ./classes

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

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

      cd /usr/local/solr/solrhome/collection1/conf/

      vim schema.xml

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

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

    设置业务系统Field(type="text_ik"要分词(string不分词),indexed="true"要索引,stored="true"要存储)

<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_desc" type="text_ik" indexed="true" stored="false" /> <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"/>
<copyField source="item_desc" dest="item_keywords"/>

  第四步:重启tomcat

    cd /usr/local/solr/apache-tomcat-7.0.52/bin

    [root@localhost bin]# ./startup.sh

2.3. 搜索服务工程搭建

可以参考taotao-manager创建。

  taotao-search(聚合工程pom

    |--taotao-search-interface(jar

    |--taotao-search-Service(war

(1)taotao-search的pom.xml:

<modules>
<module>taotao-search-interface</module>
<module>taotao-search-service</module>
</modules>
<build>
<plugins>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8084</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>

(2)taotao-search-interface的pom.xml:

  依赖taotao-commom、taotao-manager-pojo

(3)taotao-search-service的pom.xml:

<dependencies>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-search-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<!-- 跳过测试 -->
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>

配置文件:

applicationContext-dao.xml:

  由于搜索的数据涉及到3张表,需要自己定义mapper,而mapper的使用,只在搜索服务工程中,所以mapper接口及映射文件需要放在taotao-search-service工程中。

<!-- 数据源 -->
<!-- sqlsessionfactory -->
<!-- mapper扫描器 --> <context:property-placeholder location="classpath:properties/*.properties" />
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean>
<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
<!-- 只用于搜索的mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.search.mapper" />
</bean>

3.   测试使用solrJ管理索引库

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

3.1. 添加文档

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

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

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

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

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

  第6步:提交。

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

3.2. 删除文档

3.2.1.    根据id删除

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

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

  第3步:提交。

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

3.2.2.    根据查询删除

    @Test
public void deleteDocumentByQuery() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://192.168.25.131:8080/solr");
solrServer.deleteByQuery("title:change.me");
solrServer.commit();

3.3. 查询索引库

查询步骤:

  第1步:创建一个SolrServer对象

  第2步:创建一个SolrQuery对象。

  第3步:向SolrQuery中添加查询条件、过滤条件。。。

  第4步:执行查询。得到一个Response对象。

  第5步:取查询结果。

  第6步:遍历结果并打印。

3.3.1.    简单查询

@Test
public void queryDocument() throws Exception {
// 第一步:创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.25.131:8080/solr");
// 第二步:创建一个SolrQuery对象。
SolrQuery query = new SolrQuery();
// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
query.setQuery("*:*");
// 第四步:执行查询。得到一个Response对象。
QueryResponse response = solrServer.query(query);
// 第五步:取查询结果。
SolrDocumentList solrDocumentList = response.getResults();
System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
// 第六步:遍历结果并打印。
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
}
}

3.3.2.    带高亮显示

  @Test
public void queryDocumentWithHighLighting() throws Exception {
// 第一步:创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
// 第二步:创建一个SolrQuery对象。
SolrQuery query = new SolrQuery();
// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
query.setQuery("测试");
//指定默认搜索域
query.set("df", "item_keywords");
//开启高亮显示
query.setHighlight(true);
//高亮显示的域
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
// 第四步:执行查询。得到一个Response对象。
QueryResponse response = solrServer.query(query);
// 第五步:取查询结果。
SolrDocumentList solrDocumentList = response.getResults();
System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
// 第六步:遍历结果并打印。
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮显示
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String itemTitle = null;
if (list != null && list.size() > 0) {
itemTitle = list.get(0);
} else {
itemTitle = (String) solrDocument.get("item_title");
}
System.out.println(itemTitle);
System.out.println(solrDocument.get("item_price"));
}
}

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

  域包括tb_item(商品表),tb_item_cat(商品类目表),tb_item_desc(商品描述表)这三张表的数据。

  要实现功能:从数据库将数据导出来后,导入到索引库。

4.1. 功能分析

  在schema.xml中定义以下业务域(已经定义好):

    商品Id

    商品标题

    商品卖点

    商品价格

    商品图片

    分类名称

    商品描述

  

  需要从tb_item, tb_item_cat, tb_item_desc表中查询数据。

  Sql语句:(返回值是列表,需要有一个POJO封装一行记录,再存放到List中返回)

    SELECT
    a.id, a.title, a.sell_point, a.price, a.image, b. NAME category_name, c.item_desc
    FROM
     tb_item a, tb_item_cat b, tb_item_desc c
    WHERE
    a.cid = b.id
    AND a.id = c.item_id
    AND a.`status` = 1;

应该在taotao-manager-web工程中调用导入索引库的服务。

  在taotao-manager-web后台系统中 做一个导入索引库的功能界面(例如:有个按钮,点击即可将数据从数据库中导入到索引库)。

  

  业务逻辑:

    1、点击按钮,表现层调用服务层的工程的导入索引库的方法

    2、服务层实现 调用mapper接口的方法查询所有的商品的数据

    3、将数据一条条添加到solrinputdocument文档中

    4、将文档添加到索引库中

    5、提交,并返回导入成功即可

4.2. Dao层

4.2.1.    创建POJO

  创建以下POJO用于存放查询到的用于搜索的商品的数据,并放入taotao-common中

/**
* 搜索的商品数据POJO
*/
public class SearchItem implements Serializable {
private Long id; //商品的id
private String title;//商品标题
private String sell_point;//商品卖点
private Long price; //价格
private String image;//商品图片的路径
private String category_name;//商品分类名称
private String item_desc;//商品的描述
set/get......
}

4.2.2.    定义mapper接口

接口(SearchItemMapper)

/**
* 定义mappre,关联查询3张表 查询出搜索时的商品数据
*/
public interface SearchItemMapper {
//查询所有商品数据
public List<SearchItem> getSearchItemList();
}

4.2.3.    Mapper映射文件(SearchItemMapper.xml)

<?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="com.taotao.search.mapper.SearchItemMapper" >
<select id="getSearchItemList" resultType="com.taotao.common.pojo.SearchItem">
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b. NAME category_name,
c.item_desc
FROM
tb_item a,
tb_item_cat b,
tb_item_desc c
WHERE
a.cid = b.id
AND a.id = c.item_id
AND a.status = 1 </select>
</mapper>

4.3. Service层

  参数:无

  业务逻辑:taotao-search中实现

    1、查询所有商品数据。

    2、创建一个SolrServer对象。

    3、为每个商品创建一个SolrInputDocument对象。

    4、为文档添加域

    5、向索引库中添加文档。

    6、返回TaotaoResult。

4.3.1.    创建applicationContext-solr.xml

  在 applicationContext-solr.xml中配置SolrServer对象。

    <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg name="baseURL" value="http://192.168.25.131:8080/solr"></constructor-arg>
</bean>

4.3.2.    定义service接口

  接口:

public interface SearchService {
/**
* 导入所有的商品数据到索引库中
*/
public TaotaoResult importAllItems() throws Exception;
}

4.3.3.    service实现类

taotao-search-service 的 com.taotao.search.service.impl 包下:

@Service
public class SearchServiceImpl implements SearchService { // 1.注入mapper
@Autowired
private SearchItemMapper searchItemMapper; @Autowired
private SolrServer solrServer; @Override
public TaotaoResult importAllItems() throws Exception {
//2.调用mapper的方法,查询所有的商品的数据
List<SearchItem> searchItemList = searchItemMapper.getSearchItemList();
//3.通过solorj将数据写入到索引库中
//3.1 创建httpSolrServer(配置文件applicationContext-solr.xml已经创建了)
//3.2 创建SolrInputDocument ,将列表searchItemList中的元素一个个放到索引库中
for(SearchItem searchItem:searchItemList){
//为每个商品创建一个SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
//为文档添加域
document.addField("id", searchItem.getId().toString());//这里是字符串需要转换
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());
document.addField("item_desc", searchItem.getItem_desc());
//添加到索引库
solrServer.add(document);
}
//提交
solrServer.commit();
//4.返回TaotaoResult
return TaotaoResult.ok();
}
}

4.3.4.    在taotao-search-service中发布服务

<!-- 使用dubbo发布服务 -->
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="taotao-search" />
<dubbo:registry protocol="zookeeper" address="192.168.25.131:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20882" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.search.service.SearchService" ref="searchServiceImpl" timeout="300000"/>

4.4. 表现层

4.4.1.    创建JSP(前端页面实现)

  index.jsp中添加网站索引管理:

  

  在taotao-manager-web中创建 indexManager.jsp :

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<div>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="importAll()">一键导入商品数据到索引库</a>
</div> <script type="text/javascript">
// 通过ajax 发送请求
function importAll(){
$.ajax({
url:"/index/importAll",
type:"GET",
success:function(data){
//taotaoresult
if(data.status==200){
alert("导入成功");
}else{
alert("导入失败");
}
} });
}
</script>

4.4.2.  引用服务

  在 taotao-manager-web 中的 springmvc.xml 引用服务。

<dubbo:reference interface="com.taotao.search.service.SearchService" id="searchService" timeout="300000"/>

4.4.3.  添加taotao-search-interface的依赖

  在taotao-manager-web工程中的pom.xml中添加

4.4.4.   Controller

  请求的url:/index/importAll

  参数:无

  返回值:json数据。TaotaoResult。

@Controller
public class SearchItemController { @Autowired
private SearchService searchService;
/**
* 导入所有的商品数据到索引库中
* @return
*/
@RequestMapping("/index/importAll")
@ResponseBody
public TaotaoResult importAllItems(){ try {
return searchService.importAllItems();
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, "导入数据失败");
}
}
}

4.4.5.    测试

  测试出错,原因是未将工程中的映射文件发布到classpath中。

  在taotao-search-service工程的pom文件中添加如下配置:

<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<!-- 如果没有此节点,src/main/resources目录下的配置文件将被忽略 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

还需要在taotao-search-service中加入mybatis和数据库连接池的依赖:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<!-- 分页插件pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency> <!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>

效果:

导入成功后solr索引库数据:

5.   商品搜索功能实现

5.1. 搜索表现层工程搭建

  搜索结果页面的展示。

  Taotao-search-web,打包方式war。可以参考taotao-manager-web创建。

5.1.1.    Pom文件

 <dependencies>
<!-- common -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- search-interface -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-search-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency> <!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8085</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>

5.1.2.    配置文件

springmvc.xml:

<!-- 组件扫描 -->
<!-- 注解驱动 -->
<!-- 视图解析器 -->
<!-- 调用服务 -->
<context:component-scan base-package="com.taotao.search.controller" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean> <!-- 引用dubbo服务 -->
<dubbo:application name="taotao-search-web" />
<dubbo:registry protocol="zookeeper" address="192.168.25.131:2181" />
<!-- <dubbo:reference interface="com.taotao.search.service.SearchItemService" id="searchItemService" timeout="30000"/> -->

web.xml:

<display-name>taotao-search-web</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>taotao-search-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>taotao-search-web</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

5.1.3.    静态页面

5.2. 搜索功能分析

  在首页的搜索框中输入搜索条件,然后跳转到搜索结果页面。搜索结果页面在taotao-search-web工程中。

  

  首页搜索框的点击按钮处理函数在:首页的JS中,应当改成8085,如图:

  

  请求的url/search

  http://localhost:8085/search.html?q=

  参数

    1、q 查询条件。

    2、page 页码。默认为1   每页显示多少行 在controller中写死即可。比如:60

  返回值: String。(商品的列表信息,总页数 ,总记录数,数据回显)   定义一个返回结果类SearchResult,存放商品的列表信息,总页数 ,总记录数。

  业务逻辑

    1、接收查询条件。

    2、创建一个SolrServer对象,需要注入。

    3、创建一个SolrQuery对象。

    4、需要设置查询条件、分页条件、设置默认搜索域、高亮设置。

    5、执行查询,返回QueryResponse对象。

    6、取返回结果,封装到List<SearchItem>中。

    7、返回查询结果的总记录数,计算查询结果的总页数。

    8、得到查询结果,渲染jsp.

5.3. Dao层

5.3.1.    功能分析

  访问索引库的类。定义一些通用的数据访问方法。(注:不能用逆向工程了。dao层功能在taotao-search-service工程中的com.taotao.search.dao包中定义)

  业务逻辑就是查询索引库。

  参数:SolrQuery对象

  业务逻辑:

    1、根据Query对象进行查询。

    2、返回查询结果。包括List<SearchItem>、查询结果的总记录数。

  需要把返回结果封装到pojo中,至少包含两个属性:List<SearchItem>、Long recordCount。再包含一个总页数。

  创建如下SearchResult对象,放入taotao-common中

public class SearchResult implements Serializable {
private List<SearchItem> itemList;//搜索结果列表
private long recordCount;//总记录数
private long pageCount;//总页数
set/get......
}

5.3.2.    创建SearchDao

由于搜索功能只在搜索工程中用到,可以不写接口,只写类(将Search直接定义为类,没必要定义为接口再实现)。返回值:SearchResult

/**
* 从索引库中搜索商品的DAO
* @author smileZTT
*
*/
@Repository
public class SearchDao { //1.创建solrServer对象 由sprin管理注入
@Autowired
private SolrServer solrServer; /*根据查询条件查询商品的结果集*/
public SearchResult search(SolrQuery query) throws Exception { SearchResult searchResult = new SearchResult(); //2.直接执行查询
QueryResponse response = solrServer.query(query);
//3.获取结果集
SolrDocumentList results = response.getResults(); //4.遍历结果集
List<SearchItem> itemList = new ArrayList<SearchItem>();
for(SolrDocument solrDocument : results){
SearchItem item = new SearchItem();
item.setId(Long.parseLong(solrDocument.get("id").toString()));
item.setCategory_name(solrDocument.get("item_category_name").toString());
item.setImage(solrDocument.get("item_image").toString());
item.setPrice((long) solrDocument.get("item_price"));
item.setSell_point(solrDocument.get("item_sell_point").toString());
//取高亮显示
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
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 = solrDocument.get("item_title").toString();
}
item.setTitle(itemTitle);
//添加到商品列表
itemList.add(item);
}
//5.设置searchResult中的属性,然后返回
searchResult.setItemList(itemList);//设置搜索结果列表
searchResult.setRecordCount(results.getNumFound());//设置总记录数
return searchResult;
}
}

5.4. Service层

5.4.1.    功能分析

  参数:queryString:查询条件

      Page:页码

      Rows:每页显示的记录数。

  业务逻辑

    1、创建一个SolrQuery对象。

    2、设置查询条件

    3、设置分页条件

    4、需要指定默认搜索域。

    5、设置高亮

    6、执行查询,调用SearchDao。得到SearchResult

    7、需要计算总页数。

    8、返回SearchResult

5.4.2.   service接口

接口已存在,只需要添加方法即可。

public interface SearchService {

    /**
* 导入所有的商品数据到索引库中
*/
public TaotaoResult importAllItems() throws Exception; /**
* 根据搜索条件搜索
* @param queryString 查询的主条件
* @param page 查询的当前页码
* @param rows 每页显示的行数,这个在Controller中写死
* @return
* @throws Exception
*/
public SearchResult search(String queryString, Integer page, Integer rows) throws Exception;
}

5.4.3.  service接口实现类  SearchServiceImpl :

@Service
public class SearchServiceImpl implements SearchService { @Autowired
private SearchDao searchDao; @Override
public SearchResult search(String queryString, Integer page, Integer rows)
throws Exception { //1.创建solrQuery对象
SolrQuery query = new SolrQuery(); //2.设置主查询条件
if(StringUtils.isNotBlank(queryString)){
query.setQuery(queryString);
}else {
query.setQuery("*:*");
}
//2.1 设置过滤条件 设置分页
if(page == null) page = 1;
if(rows == null) rows = 60;
query.setStart((page - 1) * rows);
query.setRows(rows);
//2.2 设置默认的搜索域
query.set("df", "item_keywords");
//2.3 设置高亮
query.setHighlight(true);//开启高亮
query.addHighlightField("item_title");//设置高亮显示的域
query.setHighlightSimplePre("<em style=\"color:red\">");
query.setHighlightSimplePost("</em>"); //3.利用dao方法返回的SearchResult只包含了总记录数和商品列表
SearchResult result = searchDao.search(query); //4.设置SearchResult的总页数
long recordCount = result.getRecordCount();
long pageCount = recordCount / rows;
if(recordCount % rows > 0)
pageCount++;
result.setPageCount(pageCount); //5.返回
return result;
}
}

5.4.4.   在taotao-search-service中发布服务

  <!-- 使用dubbo发布服务 -->
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="taotao-search" />
<dubbo:registry protocol="zookeeper" address="192.168.25.131:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20882" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.search.service.SearchService" ref="searchServiceImpl" timeout="300000"/>

5.4. 表现层

功能在 taotao-search-web 中实现。

5.4.1.   引用服务

taotao-search-web的sprinmvc.xml 中引用:

  <!-- 引用dubbo服务 -->
<dubbo:application name="taotao-search-web" />
<dubbo:registry protocol="zookeeper" address="192.168.25.131:2181" />
<dubbo:reference interface="com.taotao.search.service.SearchService" id="searchService" timeout="30000"/>

5.4.2.    Controller

  请求的url:/search

  参数

    1、q 查询条件。

    2、page 页码。默认为1

  返回值:逻辑视图,返回值。String。

  业务逻辑

    1、接收参数

    2、调用服务查询商品列表

    3、把查询结果传递给页面。需要参数回显。

@Controller
public class SearchController { @Value("${ITEM_ROWS}")
private Integer ITEM_ROWS; @Autowired
private SearchService searchService; @RequestMapping("/search")
public String search(@RequestParam("q")String queryString,
@RequestParam(defaultValue="1")Integer page, Model model) throws Exception { SearchResult result = searchService.search(queryString, page, ITEM_ROWS);
//传递给页面
model.addAttribute("query", queryString);
model.addAttribute("totalPages", result.getPageCount());
model.addAttribute("itemList", result.getItemList());
model.addAttribute("page", page); //返回逻辑视图
return "search";
}
}

属性文件中配置行数:(文件存放在taotao-search-web中的resource目录下)

还需要配置属性文件加载:在springmvc.xml中

5.4.3.    测试

测试发现有乱码,是GET请求乱码,需要对请求参数进行转码处理:

翻页处理:在taotao-search-web工程中:修改如下:

5.5. 图片显示处理

  数据库中保存的图片是以逗号分隔的url列表,只需要展示第一张图片即可。

  方法:

    1、向索引库中添加文档时,只取第一张写入索引库

    2、从文档列表转换为商品列表时可以取一张。

    3、在jsp中对列表拆分,只取一张展示。

  可以在SearchItem中添加一个getImages方法:

  

   在search.jsp中取属性:

      

商城06——solr索引库搭建&solr搜索功能实现&图片显示问题解决的更多相关文章

  1. JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

    1. 学习计划 1.Solr服务搭建 2.Solrj使用测试 3.把数据库中的数据导入索引库 4.搜索功能的实现 2. Solr服务搭建 2.1. Solr的环境 Solr是java开发. 需要安装j ...

  2. 第04项目:淘淘商城(SpringMVC+Spring+Mybatis)【第八天】(solr服务器搭建、搜索功能实现)

    https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040 ...

  3. 使用solrj操作solr索引库

    (solrj)初次使用solr的开发人员总是很郁闷,不知道如何去操作solr索引库,以为只能用<五分钟solr4.5教程(搭建.运行)>中讲到的用xml文件的形式提交数据到索引库,其实没有 ...

  4. 使用solrj操作solr索引库,solr是lucene服务器

    客户端开发 Solrj 客户端开发 Solrj Solr是搭建好的lucene服务器 当然不可能完全满足一般的业务需求 可能 要针对各种的架构和业务调整 这里就需要用到Solrj了 Solrj是Sol ...

  5. 如何在分布式环境中同步solr索引库和缓存信息

    天气依旧很好,主要是凉快.老习惯,我在北京向各位问好. 搜索无处不在,相信各位每天都免不了与它的亲密接触,那么我想你确实有必要来了解一下它们,就上周在公司实现的一个小需求来给各位分享一下:如何在分布式 ...

  6. 将数据库的数据导入solr索引库中

    在solr与tomcat整合文章中,我用的索引库是mycore,现在就以这个为例. 首先要准备jar包:solr-dataimporthandler-4.8.1.jar.solr-dataimport ...

  7. solr索引库的创建

    solr索引库的创建 一.找到你安装的[solrhome]目录(我的是这个) 二.进入该目录 三.选择其中任意一个索引库复制一份到该目录下并更名为要创建的索引库名称 四.进入[myindex]目录下, ...

  8. 数据添加到solr索引库后前台如何搜索

    主要结构: 查询 Dao: package com.taotao.search.dao.impl; import java.util.ArrayList; import java.util.List; ...

  9. solr 索引库的维护

    一.配置中文分析器:IK-analyzer,在FieldType中指定中文分析器:1 复制IK-analyzer到你的服务器指定目录中.2 在该目录中,我们需要的东西有:IKAnalyzer的jar包 ...

随机推荐

  1. oracle 多表连接查询 join

    转 简介: 多表连接查询通过表之间的关联字段,一次查询多表数据. 下面将依次介绍 多表连接中的如下方法: 1.from a,b 2.inner join 3.left outer join 4.rig ...

  2. centos 7 vscode cmake 编译c++工程

    一.环境说明 1)gcc/g++  cmake安装建议 gcc/g++内核自带的即可,如果需要新的自行安装, cmake也一样,如有需要新的版本自行安装. 2)vscode安装插件 必要的插件c/c+ ...

  3. Java——异常处理,数据库连接

    在学习数据库连接时看到try(){}结构,查了一下写在这里: import java.sql.Connection; import java.sql.DriverManager; import jav ...

  4. redis使用技巧十连胜,学会工作六到飞起

    Redis 在当前的技术社区里是非常热门的.从来自 Antirez 一个小小的个人项目到成为内存数据存储行业的标准,Redis已经走过了很长的一段路. 随之而来的一系列最佳实践,使得大多数人可以正确地 ...

  5. [批处理教程之Shell]001.文本处理

    在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的command和后来的cmd.exe.它接收用户命令,然后调用相应的应用程序. 同时 ...

  6. [Python3]为什么map比for循环快

    实验结论 如果需要在循环结束后获得结果,推荐列表解析: 如果不需要结果,直接使用for循环, 列表解析可以备选; 除了追求代码优雅和特定规定情境,不建议使用map 如果不需要返回结果 这里有三个pro ...

  7. PAT 1036 Boys vs Girls (25分) 比大小而已

    题目 This time you are asked to tell the difference between the lowest grade of all the male students ...

  8. jchdl - GSL Port

    https://mp.weixin.qq.com/s/DVmMrCFgNLuZDtssQ85w7A   org.jchdl.model.gsl.core.meta.Port.java   ​​ gen ...

  9. ROS入门笔记(二):ROS安装与环境配置及卸载(重点)

    ROS入门笔记(二):ROS安装与环境配置及卸载(重点) [TOC] 1 ROS安装步骤 1.1 ROS版本 ROS目前只支持在Linux系统上安装部署, 它的首选开发平台是Ubuntu. 发布时间 ...

  10. MethodHandle(方法句柄)系列之二:方法句柄的简单使用

     二话不说,上代码 /** * * @author LiuYeFeng<897908343@qq.com> * @date 2015年4月8日 下午10:41:13 * @CopyRigh ...