1. Solr概述
1.1. 什么是Solr
Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。
Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
1.2. 下载
从Solr官方网站(http://lucene.apache.org/solr/ )下载Solr4.10.3,根据Solr的运行环境,Linux下需要下载lucene-4.10.3.tgz,windows下需要下载lucene-4.10.3.zip。
Solr使用指南可参考:https://wiki.apache.org/solr/FrontPage。
lucene-4.10.3.zip解压:
-
bin:solr的运行脚本
-
contrib:solr的一些贡献软件/插件,用于增强solr的功能。
-
dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。
-
docs:solr的API文档
-
example:solr工程的例子目录:
- example/solr: 该目录是一个包含了默认配置信息的Solr的Core目录。
- example/multicore:该目录包含了在Solr的multicore中设置的多个Core目录。
- example/webapps: 该目录中包括一个solr.war,该war可作为solr的运行实例工程。
-
licenses:solr相关的一些许可信息
Solr的版本:4.10.3
1.3. 安装步骤
上传文件
jdk
查看Java版本:java -version
tomcat
tar -zxf apache-tomcat-7.0.47.tar.gz
创建目录路:mkdir /usr/local/solr
拷贝:cp apache-tomcat-7.0.47 /usr/local/solr/tomcat -r
solr
解压:tar -zxf solr-4.10.3.tgz.tgz
/export/decompression/solr-4.10.3/dist/solr-4.10.3.war包部署到tomcat下。并改名为solr.war
cd /export/decompression/solr-4.10.3/dist/
cp solr-4.10.3.war /usr/local/solr/tomcat/webapps/solr.war
解压war包。启动tomcat自动解压。关闭tomcat。删除solr.war.
cd /usr/local/solr/tomcat/
打开:bin/startup.sh
日志:tail -f logs/catalina.out
关闭:bin/shutdown.sh
cd webapps/
rm -f solr.war
把/export/decompression/solr-4.10.3/example/lib/ext/目录下所有的jar包复制到solr工程中。
cd /export/decompression/solr-4.10.3/example/lib/ext/
cp * /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/
创建solrhome。
Solrhome是存放solr服务器所有配置文件的目录(example下的solr目录是存放配置文件的目录,将其复制到 /usr/local/solr/solrhome下)。
cd /export/decompression/solr-4.10.3/example/
cp -r solr /usr/local/solr/solrhome
指定solr服务器solrhome的位置。
需要修改solr工程的web.xml文件。
cd /usr/local/solr/tomcat/webapps/solr/WEB-INF/
vim web.xml
去掉注释
修改< env-entry-value>标签
启动tomcat
cd /usr/local/solr/tomcat/
bin/startup.sh
访问:http://192.168.10.140:8080/solr
1.4. 配置业务字段
-
在solr中默认是中文分析器,需要手工配置。配置一个FieldType,在FieldType中指定中文分析器。
-
Solr中的字段必须是先定义后使用。
1.4.1.中文分析器的配置
使用IK-Analyzer。把分析器的文件夹上传到服务器。
需要把分析器的jar包添加到solr工程中。
cd /export/decompression/IKAnalyzer/
cp IKAnalyzer2012FF_u1.jar /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/
需要把IKAnalyzer需要的扩展词典及停用词词典、配置文件复制到solr工程的classpath
cd /usr/local/solr/tomcat/webapps/solr/WEB-INF/
mkdir classes
cd /export/decompression/IKAnalyzer/
cp IKAnalyzer.cfg.xml ext_stopword.dic mydict.dic /usr/local/solr/tomcat/webapps/solr/WEB-INF/classes
注意:扩展词典及停用词词典的字符集必须是utf-8。不能使用windows记事本编辑。
配置fieldType。需要在solrhome/collection1/conf/schema.xml中配置。
技巧:使用vi、vim跳转到文档开头gg。跳转到文档末尾:G
vi /usr/local/solr/solrhome/collection1/conf/schema.xml
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
1.4.2 业务字段配置
业务字段判断标准:
1、在搜索时是否需要在此字段上进行搜索。例如:商品名称、商品的卖点、商品的描述
2、后续的业务是否需要用到此字段。例如:商品id。
需要用到的字段:
1、商品id
2、商品title
3、卖点
4、价格
5、商品图片
6、商品分类名称
7、商品描述
Solr中的业务字段:
1、id——》商品id
其他的对应字段创建solr的字段。
vi /usr/local/solr/solrhome/collection1/conf/schema.xml
<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/tomcat
bin/shutdown.sh
bin/startup.sh
访问:http://192.168.10.140:8080/solr
找一段中文放入Field Value(Index)中
点击【analyse values】
1.5维护索引库
添加:添加一个json格式的文件就可以。
查看
修改:在solr中没有update,只需要添加一个新的文档,要求文档id和被修改文档的id一致。原理是先删除后添加。
删除:使用xml格式。
删除两种方法:
1、根据id删除:
<delete>
<id>test001</id>
</delete>
<commit/>
2、根据查询删除:
<delete>
<query>*:*</query>
</delete>
<commit/>
2. solrJ客户端
2.1 需要依赖solrj的jar包。
【/taotao-rest/】—【pom.xml】
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
2.2. solrj的使用
SolrJTest.java
【/taotao-rest】—【/src/test/java/】—【com/taotao/rest/test】—【SolrJTest.java】
package com.taotao.rest.test;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
public class SolrJTest {
@Test
public void addDocument() throws Exception {
// 创建一连接
SolrServer solrServer = new HttpSolrServer("http://192.168.10.140:8080/solr");
// 创建一个文档对象
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "test001");
document.addField("item_title", "测试商品2");
document.addField("item_price", 54321);
// 把文档对象写入索引库
solrServer.add(document);
// 提交
solrServer.commit();
}
@Test
public void deleteDocument() throws Exception {
// 创建一连接
SolrServer solrServer = new HttpSolrServer("http://192.168.10.140:8080/solr");
// solrServer.deleteById("test001");
solrServer.deleteByQuery("*:*");
solrServer.commit();
}
}
2.3 把商品信息导入到索引库
使用java程序读取mysql数据库中的商品信息,然后创建solr文档对象,把商品信息写入索引库。
需要发布一个服务。
为了灵活的进行分布式部署需要创建一搜素的服务工程发布 搜素服务。Taotao-search。
2.3.1 系统架构
2.3.2创建taotao-search工程
自动生成web.xml
2.3.3 Pom文件
需要依赖taottao-common工程
需要依赖的jar包:
Spring的jar包
Springmvc的jar包。
Solrj的jar包。
Mybatis的jar包。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-mapper</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>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
</dependencies>
<build>
<!-- 配置插件 -->
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8083</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3.4 Web.xml
【/taotao-search】—【/src/main/webapp/WEB-INF/】—【web.xml】
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="taotao" version="2.5">
<display-name>taotao-search</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 解决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</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</servlet-name>
<url-pattern>/search/*</url-pattern>
</servlet-mapping>
</web-app>
2.3.5 框架整合
参考taotao-rest工程
SqlMapConfig.xml
可删可不删
db.properties
保留
resource.properties
删除内容
applicationContext-dao.xml
添加并创建包
applicationContext-jedis.xml
删除
applicationContext-service.xml
修改并创建包
applicationContext-trans.xml
删除
springmvc.xml
修改并创建包
2.4导入商品数据
2.4.1 需要使用的表
2.4.2 Sql语句
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b.`name` category_name,
c.item_desc
FROM
tb_item a
LEFT JOIN tb_item_cat b ON a.cid = b.id
LEFT JOIN tb_item_desc c ON a.id = c.item_id
2.4.3. Dao层
需要创建一个mapper接口+mapper映射文件。名称相同且在同一目录下。
2.4.3.1pojo
创建一个sql语句对应的pojo。
Item.java
【/taotao-search】—【/src/main/java/】—【com/taotao/search/pojo/】—【Item.java】
package com.taotao.search.pojo;
public class Item {
private String id;
private String title;
private String sell_point;
private long price;
private String image;
private String category_name;
private String item_des;
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 getItem_des() {
return item_des;
}
public void setItem_des(String item_des) {
this.item_des = item_des;
}
}
2.4.3.2 接口定义
ItemMapper.java
【/taotao-search】—【/src/main/java/】—【com/taotao/search/mapper/】—【ItemMapper.java】
package com.taotao.search.mapper;
import java.util.List;
import com.taotao.search.pojo.Item;
public interface ItemMapper {
List<Item> getItemList();
}
2.4.3.3Mapper文件
ItemMapper.xml
【/taotao-search】—【/src/main/java/】—【com/taotao/search/mapper/】—【ItemMapper.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.ItemMapper">
<select id="getItemList" resultType="com.taotao.search.pojo.Item">
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
</select>
</mapper>
2.4.4. Service层
功能:导入所有的商品数据。没有参数。返回结果TaotaoResult。从数据库中查询出所有的商品数据。创建一个SolrInputDocument对象,把对象写入索引库。
ItemService.java
【/taotao-search/】—【src/main/java/】—【com/taotao/search/service/】—【ItemService.java】
package com.taotao.search.service;
import com.taotao.common.utill.TaotaoResult;
public interface ItemService {
TaotaoResult importAllItems();
}
ItemServiceImpl.java
【/taotao-search/】—【src/main/java/】—【com/taotao/search/service/impl/】—【ItemServiceImpl.java】
package com.taotao.search.service.impl;
import java.util.List;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.taotao.common.utill.ExceptionUtil;
import com.taotao.common.utill.TaotaoResult;
import com.taotao.search.mapper.ItemMapper;
import com.taotao.search.pojo.Item;
import com.taotao.search.service.ItemService;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private SolrServer solrServer;
@Override
public TaotaoResult importAllItems() {
try {
// 查询商品列表
List<Item> list = itemMapper.getItemList();
// 把商品信息写入索引库
for (Item item : list) {
// 创建一个SolrInputDocument对象
SolrInputDocument document = new SolrInputDocument();
document.setField("id", item.getId());
document.setField("item_title", item.getTitle());
document.setField("item_sell_point", item.getSell_point());
document.setField("item_price", item.getPrice());
document.setField("item_image", item.getImage());
document.setField("item_category_name", item.getCategory_name());
document.setField("item_desc", item.getItem_des());
// 写入索引库
solrServer.add(document);
}
// 提交修改
solrServer.commit();
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok();
}
}
resource.properties
【/taotao-search】—【/src/main/resources/resource/】—【resource.properties】
#solr服务地址
SOLR.SERVER.URL=http://192.168.10.140:8080/solr
applicationContext-dao.xml
【/taotao-search/】—【src/main/resources/spring/】—【applicationContext-dao.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.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 配置SolrServer对象 -->
<!-- 单机版 -->
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg name="baseURL" value="${SOLR.SERVER.URL}"></constructor-arg>
</bean>
</beans>
2.4.5 Controller层
功能:发布一个rest形式的服务。调用Service的服务方法,把数据导入到索引库中,返回TaotaoResult。
ItemController.java
【/taotao-search/】—【src/main/java/】—【com/taotao/search/controller/】—【ItemController.java】
package com.taotao.search.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.taotao.common.utill.TaotaoResult;
import com.taotao.search.service.ItemService;
/**
* 索引库维护
*/
@Controller
@RequestMapping("/manager")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 导入商品数据到索引库
*/
@RequestMapping("/importall")
@ResponseBody
public TaotaoResult importAllItems() {
TaotaoResult result = itemService.importAllItems();
return result;
}
}
pom.xml
【/taotao-search/】—【pom.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>
访问http://localhost:8083/search/manager/importall
http://192.168.10.140:8080/solr
3. 搜索服务发布
3.1. 需求分析
http形式的服务。对外提供搜索服务是一个get形式的服务。调用此服务时需要查询条件,分页条件可以使用page(要显示第几页)、rows(每页显示的记录数)。返回一个json格式的数据。可以使用TaotaoResult包装一个商品列表转换成json。
请求的url:/search/query/{查询条件}/{page}/{rows}
/search/query?q={查询条件}&page={page}&rows={rows}
返回的结果:TaotaoResult包装商品列表。
3.2. Dao层
分析:尽可能的做的通用一些。参数应该是SolrQuery。返回商品列表、查询结果总记录数
SolrJTest.java
【/taotao-rest】—【/src/test/java/】—【com/taotao/rest/test】—【SolrJTest.java】
package com.taotao.rest.test;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
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.junit.Test;
public class SolrJTest {
@Test
public void addDocument() throws Exception {
// 创建一连接
SolrServer solrServer = new HttpSolrServer("http://192.168.10.140:8080/solr");
// 创建一个文档对象
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "test001");
document.addField("item_title", "测试商品2");
document.addField("item_price", 54321);
// 把文档对象写入索引库
solrServer.add(document);
// 提交
solrServer.commit();
}
@Test
public void deleteDocument() throws Exception {
// 创建一连接
SolrServer solrServer = new HttpSolrServer("http://192.168.10.140:8080/solr");
// solrServer.deleteById("test001");
solrServer.deleteByQuery("*:*");
solrServer.commit();
}
@Test
public void queryDocument() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://192.168.37.163:8080/solr");
// 创建一个查询对象
SolrQuery query = new SolrQuery();
// 设置查询条件
query.setQuery("*:*");
query.setStart(20);
query.setRows(50);
// 执行查询
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"));
System.out.println(solrDocument.get("item_image"));
}
}
}
返回结果pojo:
SearchResult.java
【/taotao-search】—【/src/main/java/】—【com/taotao/search/pojo/】—【SearchResult.java】
package com.taotao.search.pojo;
import java.util.List;
public class SearchResult {
// 商品列表
private List<Item> itemList;
// 总记录数
private long recordCount;
// 总页数
private long pageCount;
// 当前页
private long curPage;
public List<Item> getItemList() {
return itemList;
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
public long getRecordCount() {
return recordCount;
}
public void setRecordCount(long recordCount) {
this.recordCount = recordCount;
}
public long getPageCount() {
return pageCount;
}
public void setPageCount(long pageCount) {
this.pageCount = pageCount;
}
public long getCurPage() {
return curPage;
}
public void setCurPage(long curPage) {
this.curPage = curPage;
}
}
SearchDao.java
【/taotao-search/】—【src/main/java/】—【com/taotao/search/dao/】—【SearchDao.java】
package com.taotao.search.dao;
import org.apache.solr.client.solrj.SolrQuery;
import com.taotao.search.pojo.SearchResult;
public interface SearchDao {
SearchResult search(SolrQuery query) throws Exception;
}
SearchDaoImpl.java
【/taotao-search/】—【src/main/java/】—【com/taotao/search/dao/impl/】—【SearchDaoImpl.java】
package com.taotao.search.dao.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.taotao.search.dao.SearchDao;
import com.taotao.search.pojo.Item;
import com.taotao.search.pojo.SearchResult;
/**
* 商品搜索Dao
* @author Lenovo
*
*/
@Repository
public class SearchDaoImpl implements SearchDao {
@Autowired
private SolrServer solrServer;
@Override
public SearchResult search(SolrQuery query) throws Exception {
// 返回值对象
SearchResult result = new SearchResult();
// 根据查询条件查询索引库
QueryResponse queryResponse = solrServer.query(query);
// 取查询结果
SolrDocumentList solrDocumentList = queryResponse.getResults();
// 取查询结果总数量
result.setRecordCount(solrDocumentList.getNumFound());
// 商品列表
List<Item> itemList = new ArrayList<>();
// 取高亮显示
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
// 取商品列表
for (SolrDocument solrDocument : solrDocumentList) {
// 创建一商品对象
Item item = new Item();
item.setId((String) 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");
}
item.setTitle(title);
item.setImage((String) solrDocument.get("item_image"));
item.setPrice((long) solrDocument.get("item_price"));
item.setSell_point((String) solrDocument.get("item_sell_point"));
item.setCategory_name((String) solrDocument.get("item_category_name"));
// 添加的商品列表
itemList.add(item);
}
result.setItemList(itemList);
return result;
}
}
3.3. Service层
功能:接收查询条件。查询条件及分页条件(page、rows),创建一个SolrQuery对象。指定查询条件、分页条件、默认搜索域、高亮显示。调用dao层执行查询。得到查询结果计算总页数。返回SearchResult对象。
SearchService.java
/taotao-search/src/main/java/com/taotao/search/service/SearchService.java
package com.taotao.search.service;
import com.taotao.search.pojo.SearchResult;
public interface SearchService {
SearchResult search(String queryString, int page, int rows) throws Exception;
}
SearchServiceImpl.java
/taotao-search/src/main/java/com/taotao/search/service/impl/SearchServiceImpl.java
package com.taotao.search.service.impl;
import org.apache.solr.client.solrj.SolrQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.taotao.search.dao.SearchDao;
import com.taotao.search.pojo.SearchResult;
import com.taotao.search.service.SearchService;
/**
* 搜索Service
* @author Lenovo
*
*/
@Service
public class SearchServiceImpl implements SearchService {
@Autowired
private SearchDao searchDao;
@Override
public SearchResult search(String queryString, int page, int rows) throws Exception {
//创建查询对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery(queryString);
//设置分页
query.setStart((page - 1) * rows);
query.setRows(rows);
//设置默认搜素域
query.set("df", "item_keywords");
//设置高亮显示
query.setHighlight(true);
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em style=\"color:red\">");
query.setHighlightSimplePost("</em>");
//执行查询
SearchResult searchResult = searchDao.search(query);
//计算查询结果总页数
long recordCount = searchResult.getRecordCount();
long pageCount = recordCount / rows;
if (recordCount % rows > 0) {
pageCount++;
}
searchResult.setPageCount(pageCount);
searchResult.setCurPage(page);
return searchResult;
}
}
3.4 Controller层
接收查询参数:查询条件、page、rows
调用Service执行查询返回一个查询结果对象。
把查询结果包装到TaotaoResult中返回,结果是json格式的数据。
如果查询条件为空,返回状态码:400,消息:查询条件不能为空。
Page为空:默认为1
Rows 为空:默认为60
SearchController.java
/taotao-search/src/main/java/com/taotao/search/controller/SearchController.java
package com.taotao.search.controller;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.taotao.common.utill.ExceptionUtil;
import com.taotao.common.utill.TaotaoResult;
import com.taotao.search.pojo.SearchResult;
import com.taotao.search.service.SearchService;
/**
* 商品查询Controller
* @author Lenovo
*
*/
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@RequestMapping(value="/query", method=RequestMethod.GET)
@ResponseBody
public TaotaoResult search(@RequestParam("q")String queryString,
@RequestParam(defaultValue="1")Integer page,
@RequestParam(defaultValue="60")Integer rows) {
//查询条件不能为空
if (StringUtils.isBlank(queryString)) {
return TaotaoResult.build(400, "查询条件不能为空");
}
SearchResult searchResult = null;
try {
queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");
searchResult = searchService.search(queryString, page, rows);
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok(searchResult);
}
}
applicationContext-service.xml
/taotao-search/src/main/resources/spring/applicationContext-service.xml
扫描dao配置:
<?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.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 扫描包加载Service实现类 -->
<!-- 扫描包加载Service实现类 -->
<context:component-scan base-package="com.taotao.search">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
浏览器地址访问如下地址
http://localhost:8083/search/query?q=手机
浏览器访问如下地址
http://localhost:8083/search/query?q=手机&page=2&rows=10