1、Solr介绍
Solr 是Apache下的一个
顶级开源项目
,采用Java开发
,它是基于Lucene
的全文搜索服务器
。Solr可以独立运行
在Jetty
、Tomcat
等这些Servlet容器中。可以单独对外提供搜索和索引功能。 Solr提供了比Lucene更为丰富的查询语言
,同时实现了可配置
、可扩展
,并对索引
、搜索性能
进行了优化。 使用Solr 进行创建索引和搜索索引的实现方法很简单,如下: 创建索引:客户端(可以是浏览器也可以是Java程序)用POST 方法
向Solr 服务器
发送一个描述 Field 及其内容的 XML 文档,Solr 服务器
根据xml文档添加、删除、更新索引 。 搜索索引:客户端(可以是浏览器也可以是Java程序)用GET方法
向Solr 服务器
发送请求,然后对Solr服务器
返回xml、json等格式的查询结果进行解析
,组织页面布局。 Solr不提供构建页面UI的功能,但是Solr提供了一个管理界面
,通过管理界面可以查询Solr的配置和运行情况
。 Solr和Lucene没有视图渲染的功能。
Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文检索应用。 Lucene仅提供了完整的
查询引擎
和索引引擎
,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者以Lucene为基础构建全文检索应用。 Solr的目标是打造一款企业级的搜索引擎系统,它是基于Lucene的一个搜索引擎服务。可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎
,通过Solr也可以高效的完成站内搜索功能
。Solr比Lucene在开发全文检索功能时,更快捷、更方便。
Solr和Lucene的版本是同步更新的,最新的版本是7.5.0。 本课程使用的版本:4.10.3 下载地址:http://archive.apache.org/dist/lucene/solr/ 下载版本:4.10.3 Linux下需要下载 lucene-4.10.3.tgz windows下需要下载 lucene-4.10.3.zip 下载lucene-4.10.3.zip并解压:
目录结构详解如下:
bin:solr的运行脚本。
contrib:solr的一些扩展jar包,用于增强solr的功能。
dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。
docs:solr的API文档。
example:solr工程的例子目录:
example/solr:
该目录是一个标准的SolrHome目录,它包含一个默认的SolrCore目录collection1。
SolrHome目录:
SolrCore目录:
SolrHome是Solr运行的主目录,该目录中包括了多个SolrCore目录。SolrCore目录中包含了运行Solr实例所有的配置文件和数据文件,Solr实例就是SolrCore
。
一个SolrHome可以包括多个SolrCore(Solr实例
),每个SolrCore提供单独的搜索和索引服务。
example/multicore:
该目录包含了在Solr的multicore中设置的多个Core目录。
example/webapps:
该目录中包括一个solr.war,该war可作为solr的运行实例工程。
licenses:solr相关的一些许可信息。
solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供
Jetty(java写的Servlet容器)
,本教程使用Tocmat作为Servlet容器,相关环境如下: solr:4.10.3 jdk环境:jdk1.8.0_161(solr4.10 不能使用jdk1.7以下
) Web服务器(servlet容器
):Tomcat 8X Mysql:5X
第一步:安装tomcat,注意:
我们学习的每一个服务器需要单独整一个tomcat
,安装tomcat后需要进行相关配置。 配置参考连接:https://cloud.tencent.com/developer/article/1353297 第二步:把solr.war部署到Tomcat中,即将以下的war包,拷贝到tomcat的webapps目录下 从solr解压包下的solr-4.10.3\example\webapps目录中拷贝solr.war
第三步:使用压缩工具解压或者启动tomcat自动解压solr.war包,解压缩之后,将solr.war包删掉
第四步:添加solr的扩展服务包,jar包位置:solr-4.10.3\example\lib\ext
将以上jar包,添加到以下目录:apache-tomcat-8.5.30-solr\webapps\solr\WEB-INF\lib
第五步:添加log4j.properties,将以下目录的文件进行拷贝,文件位置:solr-4.10.3\example\resources\log4j.properties
复制到以下目录:如果没有该目录就创建它
第六步:在solr应用的web.xml文件中,指定solrhome的目录
solr/home名称必须是固定的。
第七步:solrcore的安装,安装solrcore需要先安装solrhome,前面几步我们已经安装好了solrhome了。
打开solr解压包下solr-4.10.3\example\solr文件夹,复制以下目录:
粘贴到以下目录中(就是刚创建的solrhome目录):
这样solrhome和solrcore就安装成功了。
在solrcore的conf文件夹下有一个solrconfig.xml。这个文件是用来配置SolrCore实例的相关信息。如果使用默认配置可以不用做任何修改。
它里面包含了不少标签,但是我们关注的标签为:lib标签、datadir标签、requestHandler标签。
solrcore需要添加一个扩展依赖包,通过lib标签来指定依赖包的地址。 即:在solrconfig.xml中可以加载一些扩展的jar,
solr.install.dir:
表示solrcore的目录位置(安装目录),需要如下修改:
然后将contrib和dist两个目录拷贝到E:\solr下,如下图:
2.5.2、datadir标签
每个solrcore都有自己的索引文件目录,默认在solrcore目录下的data中。
data数据目录下包括了index索引目录
和tlog日志文件目录
。
如果不想使用默认的目录也可以通过solrconfig.xml更改索引目录 ,如下:
requestHandler请求处理器,定义了索引和搜索的访问方式。 通过/update维护索引,可以完成索引的添加、修改、删除操作。
提交xml、json数据完成索引维护,索引维护小节详细介绍。
通过/select搜索索引。
设置搜索参数完成搜索,搜索参数也可以设置一些默认值,如下:
<requestHandler name="/select" class="solr.SearchHandler">
<!-- 设置默认的参数值,可以在请求地址中修改这些参数-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int><!--显示数量-->
<str name="wt">json</str><!--显示格式-->
<str name="df">text</str><!--默认搜索字段-->
</lst>
</requestHandler>
访问地址:http://localhost:8080/solr/
出现以下界面则说明solr安装配置成功!!!
仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等信息。
Solr运行日志信息。
Cloud即SolrCloud,即Solr云(集群),当使用Solr Cloud模式运行时会显示此菜单,该部分功能在第二个项目,即电商项目中会讲解。
Solr Core的管理界面。在这里可以添加SolrCore实例。
Solr在JVM 运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。
显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。
选择一个SolrCore进行详细操作,如下:
(1)Analysis(重点)
通过此界面可以测试索引分析器和搜索分析器的执行情况。
注:solr中,分析器是绑定在域的类型中的
。
(2)Dataimport
可以定义数据导入处理器,从关系数据库中将数据导入到Solr索引库中。
默认没有配置,需要手工配置。
(3)Documents(重点)
通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新
。
通过此菜单可以创建索引
、更新索引
、删除索引
等操作,界面如下:
需要在后添加
。(4)Files、Ping、Plugins/Stats这三个选项卡不重要,不解释了
(5)Query(重点)
通过/select执行搜索索引,必须指定“q”查询条件方可搜索。
(6)Replication、Schema Browser这两个选项卡不重要,不解释了
配置多SolrCore的好处: 1、一个solr工程对外通过SorlCore 提供服务,每个SolrCore相当于一个数据库,这个功能就相当于一个mysql可以运行多个数据库。 2、每个SolrCore之间是独立的,都可以单独对外提供服务。不同的业务模块可以使用不同的SolrCore来提供搜索和索引服务。 3、将索引数据分SolrCore存储,方便对索引数据管理维护。 4、在进行SolrCloud集群必须配置多SolrCore。 添加solrcore: 第一步:复制solrhome下的collection1目录到本目录下,修改名称为collection2
第二步:修改新的solrcore目录下的core.properties文件
这样多solrcore就配置完成了。
第三步:验证多solrcore是否配置成功
重新启动Tomcat访问solr服务。出现如下图所示:表示多solrcore配置成功了。
schema.xml文件在solrcore的conf目录下,如下图。它是
Solr数据表配置文件
,在此配置文件中定义了域
以及域的类型
还有其他一些配置,在solr中域必须先定义后使用,即:在solr中,Field和FieldType都需要先定义后使用
。
定义Field域:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
name:指定域的名称 type:指定域的类型,比如:指定是否分词 indexed:是否索引 stored:是否存储 required:是否必须 multiValued:是否是多值,存储多个值时设置为true,solr允许一个Field存储多个值,比如:存储一个用户的好友id(多个),商品的图片(多个,大图和小图)。
定义动态域:
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
name:动态域的名称,是一个表达式,*匹配任意字符,只要域的名称和表达式的规则能够匹配就可以使用。 例如:搜索时查询条件:product_i:钻石
,就可以匹配这个动态域,可以直接使用,不用单独再定义一个product_i域。
指定唯一键:
<uniqueKey>id</uniqueKey>
相当于主键,每个文档中必须有一个id域。其中的id是在field标签中已经定义好的域名
,而且该域要设置为required为true。一个schema.xml文件中必须有且仅有一个唯一键。
定义复制域:
<copyField source="cat" dest="text"/>
可以将多个field复制到一个field中,以便进行统一的检索。当创建索引时,solr服务器会自动的将源域的内容复制到目标域中
。 source:源域域名。 dest:目标域域名,搜索时,指定目标域为默认搜索域,可以提高查询效率。 注意:由dest指定的目标域,必须设置multiValued为true(多值)。示例如下图(以text域为例): 定义目标域:
定义域的类型:示例代码如下
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
详解如下:
name:指定域类型的名称。 class:指定域类型的solr类型。 analyzer:指定分词器。在fieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。 type:index和query。分别指定搜索和索引时的分析器。index 是创建索引,query 是查询索引。 tokenizer:指定分词器 filter:指定过滤器
使用IKAnalyzer中文分析器。 第一步:把IKAnalyzer2012FF_u1.jar添加到apache-tomcat-8.5.30-solr\webapps\solr\WEB-INF\lib目录下。
第二步:复制IKAnalyzer的配置文件、自定义词典和停用词词典到solr的classpath下,即:apache-tomcat-8.5.30-solr\webapps\solr\WEB-INF\classes。
第三步:在schema.xml中添加一个自定义的fieldType,使用中文分析器。
文件位置:E:\solr\solrhome\collection1\conf\schema.xml
第四步:在schema.xml中配置使用中文分词的field,即:定义field,指定field的type属性为text_ik。
第五步:重新启动Tomcat访问solr服务。测试结果如下:
name="title_ik"
name="content_ik"
要使用solr实现电商网站中商品搜索。 电商中商品信息在mysql数据库中存储了,将mysql数据库中数据在solr中创建索引。 需要在solr的schema.xml文件中定义商品field。即:对京东案例中的products表的数据进行索引,所以需要先定义对应的field域。
先确定定义的商品document的field有哪些? 可以根据mysql数据库中商品表的字段来确定: products商品表的表结构如下:
商品document的field包括:pid、name、catalog、catalog_name、price、description、picture
先定义fieldType:
经分析,由于中文分词器已经配置完fieldType,所以目前solr本身提供的fieldType类型够用了不用定义新的了。
再定义field:
pid:商品id主键
由于pid在products表中是唯一键,而且在solr的shema.xml中已有一个id的唯一键配置,所以不需要再重新定义pid域。使用solr本身提供的即可,如下:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
其余的需要自己定义,如下图所示:
定义目标域、定义复制域,如下图所示:
每次定义完新的域后都需要重新启动Tomcat访问solr服务,测试一下。没有问题,就可以开始下步操作啦!
该插件可以将数据库中指定的sql语句的结果导入到solr索引库中
。
(1)添加dataimport的jar
从solr-4.10.3\dist目录下拷贝solr-dataimporthandler-4.10.3.jar,复制到以下目录:
修改E:\solr\solrhome\collection1\conf\solrconfig.xml文件,添加lib标签,如下:
<lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />
(2)添加数据库驱动包
把mysql数据库驱动包,拷贝到以下目录:
修改solrconfig.xml文件,添加lib标签,如下:
<lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*\.jar" />
在collection1\conf\目录下创建data-config.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/solr"
user="root"
password="root"/>
<document>
<entity name="product" query="SELECT pid,name,catalog,catalog_name,price,description,picture FROM products ">
<field column="pid" name="id"/>
<field column="name" name="product_name"/>
<field column="catalog" name="product_catalog"/>
<field column="catalog_name" name="product_catalog_name"/>
<field column="price" name="product_price"/>
<field column="description" name="product_description"/>
<field column="picture" name="product_picture"/>
</entity>
</document>
</dataConfig>
data-config.xml文件详解如下:
出现如下界面,表示我们配置dataimportHandler插件
成功:
即:将数据库中指定的sql语句的结果导入到solr索引库中,此过程可能需要一些时间,注意:导入数据前会先清空索引库
,然后再导入。
我们可以通过点击“Refresh Status”按钮,查看导入数据的状态,最后导入数据成功的界面如下:
solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常嵌入在业务系统中,通过SolrJ的API接口操作Solr服务,如下图:
Solrj和图形界面操作的区别就类似于数据库中你使用jdbc和mysql客户端的区别一样。
第一步:演示创建普通的java工程即可
第二步:添加jar
solrj的核心包和solrj的依赖包
solr服务的扩展包
步骤 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。 2、创建SolrInputDocument对象,然后通过它来添加域。 3、通过HttpSolrServer对象将SolrInputDocument添加到索引库。 4、提交。 在solr中,索引库中都会存在一个唯一键(唯一约束),如果一个document的id存在,则执行修改操作,如果不存在,则执行添加操作。
示例代码如下:
/**
* 使用solr添加\修改索引
* @throws Exception
*/
@Test
public void insertAndUpdateIndex() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/"); // 参数:是solr服务器的访问地址
// 2、创建SolrInputDocument对象,然后通过它来添加域。
SolrInputDocument document = new SolrInputDocument();
// 第一个参数:域的名称,域的名称必须是已经在schema.xml中定义过的
// 第二个参数:域的值
// 注意:id的域不能少
document.addField("id", "c001");
document.addField("name", "hello solr");
// 3、通过HttpSolrServer对象将SolrInputDocument添加到索引库。
server.add(document);
// 4、提交。
server.commit();
}
图相化界面查询测试结果如下图所示:
(1)根据指定ID来删除索引
/**
* 使用solr根据指定ID来删除索引
* @throws Exception
*/
@Test
public void deleteIndexById() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/"); // 参数:是solr服务器的访问地址
// 2、根据指定ID来删除索引
server.deleteById("c001");
// 3、提交。
server.commit();
}
(2)根据条件删除索引
/**
* 使用solr根据指定条件来删除索引
* @throws Exception
*/
@Test
public void deleteIndexByCondition() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/"); // 参数:是solr服务器的访问地址
// 2、根据指定条件来删除索引
server.deleteByQuery("id:c001");
// 删除全部(慎用)
// server.deleteByQuery("*:*");
// 3、提交。
server.commit();
}
(1)solr的查询语法
1、q -- 查询关键字,必须的,如果查询所有使用
*:*
。 请求的q是字符串
2、fq -- (filter query)过滤查询,作用:在q查询符合结果中同时是fq查询符合的,例如:
请求fq是一个数组(多个值)
过滤查询价格从1到20的记录。
也可以在“q”查询条件中使用product_price:1 TO 20,如下:
也可以使用“*”表示无限,例如:
20以上:product_price:20 TO *
20以下:product_price:* TO 20
3.sort -- 排序,格式:sort=[<field name>+<desc|asc>],[<field name>+<desc|asc>],......
。示例:
按价格降序
4、start -- 分页显示使用,开始记录下标,从0开始。
5、rows -- 指定返回结果最多有多少条记录,配合start来实现分页。
实际开发时,知道当前页码和每页显示的个数最后求出开始下标。
6、fl -- 指定返回那些字段内容,用逗号或空格分隔多个。
7、df -- 指定一个默认搜索的field
也可以在solrcore目录中conf/solrconfig.xml文件中指定默认搜索field,指定后就可以直接在“q”查询条件中输入关键字。如下:
8、wt -- (writer type)指定输出格式,可以有xml, json, php, phps,后面是solr 1.3增加的,要用的话需要配置,因为默认没有打开。
9、hl -- 是否高亮,设置高亮field,设置格式前缀和后缀。
(2)简单查询
/**
* 简单查询
* @throws Exception
*/
@Test
public void queryIndex01() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/"); // 参数:是solr服务器的访问地址
// 2、创建SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件,名称"q"是固定的且必须的!
query.set("q", "product_name:小黄人");
// 3、调用server的查询方法,查询索引库
QueryResponse response = server.query(query);
// 4、获取查询结果
SolrDocumentList results = response.getResults();
// 5、处理查询结果
long count = results.getNumFound();
System.out.println("查询结果总数为:" + count);
for (SolrDocument solrDocument : results) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("product_name"));
System.out.println(solrDocument.get("product_price"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_picture"));
System.out.println("--------------------");
}
}
(3)复杂查询
/**
* 复杂查询
* @throws Exception
*/
@Test
public void queryIndex02() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/"); // 参数:是solr服务器的访问地址
// 2、创建SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件
// query.set("q", "product_name:小黄人");
query.setQuery("product_name:小黄人");
// 设置过滤条件,如果设置多个过滤条件的话,需要使用query.addFilterQuery(fq);
query.setFilterQueries("product_price:[1 TO 20]");
// 设置排序
query.setSort("product_price", ORDER.desc);
// 设置分页信息(使用默认的)
query.setStart(0);
query.setRows(10);
// 设置显示的field的域集合
query.setFields("id,product_name,product_catalog,product_price,product_picture");
// 设置默认域
query.set("df", "product_keywords");
// 设置高亮信息
query.setHighlight(true);
query.addHighlightField("product_name");
query.setHighlightSimplePre("<span color='red'>");
query.setHighlightSimplePost("</span>");
// 3、调用server的查询方法,查询索引库
QueryResponse response = server.query(query);
// 4、获取查询结果
SolrDocumentList results = response.getResults();
// 5、处理查询结果
long count = results.getNumFound();
System.out.println("查询结果总数为:" + count);
// 获取高亮列表
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
for (SolrDocument solrDocument : results) {
System.out.println(solrDocument.get("id"));
String productName = (String) solrDocument.get("product_name");
// 获取本文档的高亮信息
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
// 如果有高亮信息,则把商品名称赋值为有高亮的那个名称
if (list != null) {
productName = list.get(0); // 本例中list只有一条记录
}
System.out.println(productName);
System.out.println(solrDocument.get("product_price"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_picture"));
System.out.println("--------------------");
}
}
使用solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序。
界面如下:
开发人员需要的文档:静态页面(根据UI设计由美工给出)、数据库设计、原型设计
详解如下:
应用服务器服务端: 表现层:使用springmvc接收前台搜索页面的查询条件等信息。 业务层:调用dao层完成数据库持久化。 如果数据库数据发生变化,调用solrj的客户端同步索引库。 Dao层:对商品数据进行维护和查询,使用mybatis完成数据库持久化。 Solrj服务器: 提供搜索和索引服务。 数据库服务器: 提供数据库服务。
Solr:4.10.3 jdk环境:jdk1.8.0_161(solr4.10 不能使用jdk1.7以下) ide环境:Eclipse Oxygen Web服务器(servlet容器):Tomcat 8X
其中: 1、Dynamic web module version版本选择 2.5,这样兼容性好一些; 2、Default output folder设置为 WebRoot\WEB-INF\classes 3、Content directory设置为 WebRoot
注意:
2、3步骤的目的是为了跟MyEclipse兼容,其实不修改也行的。 4、更改JRE System LibraryJ2SE-1.5为 JRE System Libraryjre1.7.0_80 5、删掉没用的库:EAR Libraries 6、增加服务器运行环境库 Server Runtime,不然jsp文件会报错。 7、创建完项目后,将整个项目的编码改为UTF-8。 操作步骤:选中项目右键 --> Properties --> Resource --> Text file encoding --> Other中选择UTF-8。 8、对于动态的java web项目,为了工程目录结构的清爽,我们将引入的jar包放到“Web App Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。 9、对于普通的java项目,为了工程目录结构的清爽,我们将引入的jar包放到“Referenced Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。
solr服务的扩展包 solr服务的日志包 spring的包(包含springmvc) jstl包 commons日志包 junit包
(1)分析索引查询结果
通过分析得出:
需要一个商品的pojo(Product),存放商品信息。
还需要一个包装的pojo(ResultModel),它包括商品列表信息、商品分页信息。
(2)相应的代码
Product.java
public class Product {
// 商品编号
private String pid;
// 商品名称
private String name;
// 商品分类名称
private String catalog_name;
// 价格
private float price;
// 商品描述
private String description;
// 图片名称
private String picture;
// getter和setter
}
ResultModel.java
public class ResultModel {
// 商品列表
private List<Product> productList;
// 商品总数
private Long recordCount;
// 总页数
private int pageCount;
// 当前页
private int currentPage;
// getter和setter
}
功能:
接收service层传递过来的参数,根据参数查询索引库,返回查询结果给service。
@Repository
public class ProductDaoImpl implements ProductDao {
// 依赖注入HttpSolrServer
@Autowired
private HttpSolrServer server;
/**
* 接收service层传递过来的参数,根据参数查询索引库,返回查询结果。
* 查询商品信息,包括分页信息。
*/
public ResultModel queryProduct(SolrQuery query) throws Exception {
ResultModel result = new ResultModel();
// 通过server查询索引库
QueryResponse response = server.query(query);
// 获得查询结果
SolrDocumentList documentList = response.getResults();
// 把查询结果的总数设置到ResultModel中去
result.setRecordCount(documentList.getNumFound());
List<Product> productList = new ArrayList<Product>();
Product product = null;
// 获取高亮信息
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
for (SolrDocument solrDocument : documentList) {
product = new Product();
// 设置商品ID
product.setPid((String) solrDocument.get("id"));
// 设置商品名称
String prodName = (String) solrDocument.get("product_name");
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
if (list != null) {
prodName = list.get(0);
}
product.setName(prodName);
// 设置商品分类名称
product.setCatalog_name((String) solrDocument.get("product_catalog_name"));
// 设置商品价格
product.setPrice((Float) solrDocument.get("product_price"));
// 设置商品图片地址
product.setPicture((String) solrDocument.get("product_picture"));
// 把商品添加到商品列表集合中
productList.add(product);
}
// 把商品列表放到ResultMap中
result.setProductList(productList);
return result;
}
}
功能:
接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。
接收dao返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao dao;
/**
* 接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。
* 接收dao返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
* @throws Exception
*/
public ResultModel queryProduct(String queryString, String catalogName, String price,
String sort, Integer currentPage) throws Exception {
// 创建SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件:输入关键字
if (queryString != null && !"".equals(queryString)) {
query.setQuery(queryString);
} else {
query.setQuery("*:*");
}
// 设置商品类别过滤条件:product_catalog_name:幽默杂货
if (catalogName != null && !"".equals(catalogName)) {
query.addFilterQuery("product_catalog_name:" + catalogName);
}
// 设置商品价格区间过滤条件:product_price:[10 TO 20]
if (price != null && !"".equals(price)) {
// 传过来的price的值:0-9 10-19 20-29
String[] strings = price.split("-");
if (strings.length == 2) {
query.addFilterQuery("product_price:[" + strings[0] + " TO " + strings[1] + "]");
}
}
// 设置排序:传过来1或0,1表示降序,0表示升序。
if ("1".equals(sort)) {
query.setSort("product_price", ORDER.desc);
} else {
query.setSort("product_price", ORDER.asc);
}
// 设置分页信息
if (currentPage == null) {
currentPage = 1;
}
query.setStart((currentPage - 1) * 20);
query.setRows(20);
// 设置默认搜索域
// query.set("df", "product_keywords");
// 设置高亮信息
query.setHighlight(true);
query.addHighlightField("product_name");
query.setHighlightSimplePre("<font style=\"color:red\">");
query.setHighlightSimplePost("</font>");
ResultModel resultModel = dao.queryProduct(query);
// 设置当前页
resultModel.setCurrentPage(currentPage);
// 设置总页数
Long recordCount = resultModel.getRecordCount();
int pageCount = (int) (recordCount / 20);
if (recordCount % 20 > 0) {
pageCount++;
}
resultModel.setPageCount(pageCount);
return resultModel;
}
}
@Controller
public class ProductController {
@Autowired
private ProductService service;
@RequestMapping("list")
public String list(String queryString, String catalog_name, String price,
String sort, Integer page, Model model) throws Exception {
ResultModel resultModel = service.queryProduct(queryString, catalog_name, price, sort, page);
// 将查询结果放到result域中
model.addAttribute("result", resultModel);
// 简单类型的数据回显
model.addAttribute("queryString", queryString);
model.addAttribute("caltalog_name", catalog_name);
model.addAttribute("price", price);
model.addAttribute("sort", sort);
model.addAttribute("page", page);
return "product_list";
}
}
从以下目录中拷贝
放在项目的如下目录
图片信息放到以下目录
在服务器中进行配置虚拟目录,我们可以通过图形化界面配置,如下:
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="WebApp_ID" version="2.5">
<display-name>day66_Solr_02_JD</display-name>
<!-- SpringMVC配置 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncoding</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>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
在config包下,创建springmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
<!-- 配置扫描包 -->
<context:component-scan base-package="com.itheima" />
<!-- 配置注解驱动 -->
<mvc:annotation-driven />
<!-- jsp视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置solr服务:HttpSolrServer -->
<bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg value="http://localhost:8080/solr/"></constructor-arg>
</bean>
</beans>