Solr概述

Solr是什么

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过Http Get操作提出查找请求,并得到指定格式的返回结果。

Solr安装部署

下载Solr

官网:https://lucene.apache.org/solr/
1.png
说明:Solr与Lucene是同步更新的,课程中使用4.10.3版本
3.png
solr官网下载地址:http://archive.apache.org/dist/lucene/solr/

解压Solr

2.png

目录结构说明:

bin:solr运行脚本

contrib:solr的一些扩展jar包,用于增强solr功能

dist:build过程中生成的war和jar文件,以及一些依赖文件

docs:solr的API文档

example:solr工程的例子目录

example/solr:标准的SolrHome,包含一个默认的SolrCore

example/webapps:包含了一个solr.war,该war可作为solr的运行示例工程,我们部署的solr服务就是用的它

licenes:solr相关的许可信息

安装环境

Solr本身集成了Jetty服务器,可以直接启动运行。 Tomcat、jetty、Jboss、underTow

打开cmd命令行窗口,进入solr解压目录中的example目录。
4.png

进行cmd执行:java -jar start.jar
5.png

启动成功,访问:http://localhost:8983/solr
6.png

虽然solr内置了Jetty服务器,但是在企业中一般使用Tomcat部署

需要环境:

Solr:4.10.3

JDK环境:1.8(solr4.10 要求jdk1.7以上版本)

服务器:Tomcat 8

配置SolrHome

SolrHome目录是solr服务运行的主目录。一个SolrHome目录包含有多个SolrCore。SolrCore目录中包含了运行solr实例的配置文件和数据文件(日志和索引文件)。每一个SolrCore提供独立的索引和搜索服务。

拷贝【资料\solr-4.10.3\example\solr】目录到【D:\solr】,重命名solr为solrhome
7.png

SolrHome目录:
8.png

SolrCore目录:
9.png

说明:

conf:SolrCore运行配置信息

data:SolrCore存放日志和索引文件的目录

core.properties:SolrCore的信息,比如:名称

配置SolrCore

配置SolrCore目录下的conf/solrconfig.xml文件:
12.png

说明:solrconfig.xml文件是配置SolrCore实例的相关信息。默认情况下可以不做修改。在企业项目中需要修改三个常用的标签:lib标签、datadir标签、requestHandler标签。

lib标签

在solrconfig.xml中可以加载一些扩展的jar,如果需要使用。(一般不需要使用)

solrconfig.xml文件75-85行,修改前:
10.png

datadir标签

配置SolrCore的data目录,data目录用来存放SolrCore的索引文件和tlog日志文件。solr.data.dir表示${SolrCore}目录,等价于${solr.install.dir}
11.png

说明:一般不需要修改

requestHandler标签

requestHandler请求处理器,定义了索引和搜索的访问方式。

通过/select搜索索引,完成检索操作。
14.png

通过/update维护索引,可以完成索引的添加、修改、删除操作。
13.png

设置搜索参数完成搜索,搜索参数也可以设置一些默认值,如下:

  1. <requestHandler name="/select" class="solr.SearchHandler">
  2. <!-- default values for query parameters can be specified, these
  3. will be overridden by parameters in the request
  4. -->
  5. <lst name="defaults">
  6. <str name="echoParams">explicit</str>
  7. <int name="rows">10</int> <!-- 每页大小 -->
  8. <str name="df">text</str> <!-- 默认域 -->
  9. </lst>
  10. </requestHandler>

Solr部署

准备Tomcat

15.png

修改Tomcat访问端口

16.png
17.png

部署solr.war

第1步

拷贝solr-4.10.3\example\webapps目录中的solr.war到tomcat的webapps目录中
18.png

复制到:
19.png

第2步

解压solr.war包:
20.png

第3步

【删除solr.war包】

说明:删除为了防止tomcat启动的时候,再进行解压,覆盖已经解压配置好的solr。

第4步

【加入solr服务扩展jar包】

solr-4.10.3\example\lib\ext目录下的所有jar包copy到部署到Tomcat中的solr的/WEB-INF/lib

把solr解压包下solr-4.10.3\example\lib\ext目录下的所有jar包拷贝到Tomcat部署的solr的WEB-INF/lib文件夹
21.png

复制到:
22.png

第5步

【准备log4j.properties日志文件】

把solr解压包下solr-4.10.3\example\resources\log4j.properties文件,复制到Tomcat的webapps\solr\WEB-INF\classes目录下(如果没有classes目录,创建一个):
24.png

第6步

【配置web.xml】

修改web.xml,配置SolrHome
26.png

打开env-entry注释,修改env-entry-value为solrHome目录。
23.png

第7步

【启动tomcat服务】

运行tomcat安装bin目录中的startup.bat文件:

访问:http://localhost:8983/solr
25.png

Solr管理界面操作

Solr管理管理界面介绍

SolrCore介绍

选择一个SolrCore进行详细操作:
27.png

Analysis

通过此界面可以测试索引分析器和搜索分析器的执行情况
28.png

Dataimport

数据导入,从关系数据库将数据导入到Solr索引库中。默认没有配置,需要手工配置。

Documents

通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。
29.png

删除文档:
delete.png

<delete>
    <id>1</id>
</delete>
<commit/>

Solr使用

schema.xml

schema.xml文件在SolrCore/conf目录。主要用于配置域的类型(FieldType)和配置域(Field)。在solr中域要先配置再使用。
30.png

Field

作用:配置域。

<field name="id" type="string" indexed="true" stored="true" 
required="true" multiValued="false"/>
  • name:域的名称
  • type:域的类型
  • indexed:是否索引
  • stored:是否存储
  • required:是否必须(如果为true添加索引的时候,文档对象中必须要包含该域)
  • mulitValued:是否多值(用于复制域)

DynamicField

作用:配置动态域

<dynamicField name="*_ik"  type="text_ik" indexed="true"  stored="true"/>

name:动态域的名称

UniqueKey

作用:指定唯一约束域,相当于关系数据库中的主键

<uniqueKey>id</uniqueKey>

说明:在solr中,唯一约束域是必须的。

CopyField

作用:配置复制域

<copyField source="name" dest="keywords"/>
<copyField source="title" dest="keywords"/>
  • source:源域的名称
  • dest:目标域的名称

说明:在solr中,允许将多个域的值复制给一个域,这样的目的是方便执行搜索。solr在创建索引的时候,会把源域的内容复制给目标域。(目标域的定义必须要包含一个属性:multiValued=”true”

FieldType

作用:配置域的类型

<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:指定分词器,index是索引流程;query是检索流程
  • tokenizer:具体使用的分词器
  • filter:具体使用的过滤器

配置IK分词器

说明:配置ik中文分词器。

拷贝IK分词器jar包

拷贝Maven仓库中的jar包:
31.png

拷贝到solr/WEB-INF/lib目录:
32.png

拷贝IK分词器配置文件

拷贝IK解压目录中的配置文件:
33.png

拷贝到solr/WEB-INF/classes目录:
34.png

配置schema.xml

通过FieldType标签,配置使用IK分词器的域类型

<!-- 配置使用IK分词器的域类型 -->
<fieldType name="aaa" class="solr.TextField" >
 <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

通过Field标签,配置使用IK分词器的域

<!-- 配置使用IK分词器的域 -->
<field name="content_ik" type="aaa" indexed="false" 
stored="true" multiValued="false"/>

重启tomcat

35.png

5.3配置业务域

说明:使用solr实现商品数据的搜索,需要把保存在关系数据库中的商品数据,导入solr索引库。

5.3.1准备商品数据

导入goods.sql
36.png

商品编号(商品编号是主键,作为唯一约束域uniqueKey):

<field name="id" type="string" indexed="true" stored="true" 
required="true"/>

商品名称:

<field name="name" type="text_ik" indexed="true" stored="true"/>

商品标题:

<field name="title" type="text_ik" indexed="true" stored="true"/>

商品价格:

<field name="price" type="double" indexed="true" stored="true"/>

商品图片:

<field name="pic" type="string" indexed="false" stored="true"/>

定义商品复制域(在实际项目中复制域不需要存储,这里存储是为了给大家看到数据效果):

<field name="keywords" type="text_ik" indexed="true" stored="true" multiValued="true" />

把商品名称和商品标题添加到复制域

<copyField source="name" dest="keywords"/>
<copyField source="title" dest="keywords"/>

5.3.3配置schema.xml

<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
    <!-- 版本号(必须) -->
    <field name="_version_" type="long" indexed="true" stored="true"/>
    <!-- 普通域 -->
    <field name="id" type="string" indexed="true" stored="true" required="true"/> 
    <field name="name" type="text_ik" indexed="true" stored="true"/>
    <field name="title" type="text_ik" indexed="true" stored="true"/>
    <field name="pic" type="string" indexed="false" stored="true"/>
    <field name="price" type="double" indexed="true" stored="true"/>

    <field name="keywords" type="text_ik" indexed="true" stored="true" 
           multiValued="true"/> 

    <!-- 复制域 -->
    <copyField source="name" dest="keywords"/>
    <copyField source="title" dest="keywords"/>

    <!-- 唯一约束域 -->
    <uniqueKey>id</uniqueKey>

    <!-- 配置动态域 -->
    <dynamicField name="*_ik"  type="text_ik" indexed="true"  stored="true"/>

    <!-- 配置域类型 -->
    <fieldType name="string" class="solr.StrField"/>
    <fieldType name="boolean" class="solr.BoolField"/>
    <fieldType name="int" class="solr.TrieIntField"/>
    <fieldType name="float" class="solr.TrieFloatField"/>
    <fieldType name="long" class="solr.TrieLongField"/>
    <fieldType name="double" class="solr.TrieDoubleField"/>
    <fieldType name="date" class="solr.TrieDateField"/>

    <!-- 配置使用IK分词器的域类型 -->
    <fieldType name="text_ik" class="solr.TextField" >
        <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
    </fieldType>
</schema>

5.3.4配置solrconfig.xml 默认域

更改默认域名称,改成我们的域名称:
37.png

5.4 配置数据导入

5.4.1拷贝数据导入jar包

拷贝solr解压目录dist目录中的jar包:
38.png

拷贝到solr/solrHome/lib(lib手动创建):
40.png

5.4.2拷贝数据库驱动jar包

39.png

拷贝到solr/solrhome/lib:
41.png

5.4.3配置solrconfig.xml

第1步

配置lib标签,加载jar包
42.png

<lib dir="${solr.install.dir:../}/lib" regex=".*\.jar" />

第2步

通过requestHandler标签,配置数据导入的请求处理器
43.png

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
   <lst name="defaults">
       <str name="config">import-config.xml</str>
   </lst>
</requestHandler>

第3步

创建import-config.xml
44.png

<?xml version="1.0" encoding="UTF-8"?>
<dataConfig>

    <!-- 配置连接数据库信息 -->
    <dataSource type="JdbcDataSource"
                driver="com.mysql.jdbc.Driver"
                url="jdbc:mysql://127.0.0.1:3306/lucene_db"
                user="root"
                password="admin"/>
    <document>
        <!-- 配置sql语句中的字段,与solr索引库的域的对应关系 -->
        <entity name="goods"
                query="SELECT id,name,title,price,pic FROM goods">
            <field column="id" name="id"/>
            <field column="name" name="name"/>
            <field column="title" name="title"/>
            <field column="price" name="price"/>
            <field column="pic" name="pic"/>

            <!-- 测试动态域 -->
            <field column="pic" name="pic_ik"/>
            <field column="name" name="name_ik"/>
            <field column="title" name="title_ik"/>
        </entity>
    </document>
</dataConfig>

5.4.4重启tomcat,执行导入

45.png

查询数据

46.png

Solr管理界面搜索

q: 指定查询表达式

49.png

*:*,表示搜索全部

name:商务,表示搜索name域中包含有“商务”

fq:指定搜索的过滤条件

50.png
price:[2000 TO 8000],表示搜索2000 至8000之间的商品,包含2000 ,包含8000

price:{2000 TO 8000},表示搜索2000 至8000之间的商品,不包含2000 ,不包含8000

sort:指定搜索结果排序

51.png

price asc,表示按照商品价格升序排序

price desc,表示按照商品价格降序排序

start,rows:指定分页

52.png

start:分页开始记录数

rows:每页显示记录数

fl:指定搜索结果显示的域列表

53.png

pid,name,price,显示商品id、商品名称、商品价格

df:指定默认搜索域

54.png

注意事项:默认搜索域只能指定一个。

wt:指定搜索结果的响应格式

55.png

常用格式:json/xml/csv。

hl:指定高亮显示

56.png

hl.fl:指定高亮显示的域名称

hl.simple.pre:指定高亮显示的html标签的开始部分

hl.simple.post:指定高亮显示的html标签的结束部分
high.png

注意:高亮结果集的数据结构为:Map<String,Map<String,List<String>>

Solrj

Solrj是什么

SolrJ是一个使Java应用程序可以轻松与Solr对话的API。SolrJ隐藏了许多连接到Solr的细节,并允许您的应用程序通过简单的高级方法与Solr进行交互。

SolrJ的中心是org.apache.solr.client.solrj包,它只包含五个主要的类。首先创建一个SolrClient代表你想要使用的Solr实例。然后发送SolrRequests或SolrQuerys找回SolrResponses。

需求

使用solrj访问solr服务,完成索引的增删改查操作。

6.3 需求实现

6.3.1 创建Maven项目

配置依赖

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>com.dfbz</groupId>
    <artifactId>Solr</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--solr核心包-->
        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-core</artifactId>
            <version>4.10.3</version>
        </dependency>
        <!--solr依赖日志包-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

代码实现

添加(更新)索引

说明:solr是根据pid域执行索引的更新。先根据pid域执行搜索,搜索到执行更新;搜索不到执行添加。

  • 创建HttpSolrServer对象,连接solr服务
  • 创建域相关的实体对象(Product)
  • 使用HttpSolrServer对象,执行添加(更新)
  • 提交事务

第一步:创建域相关的实体类

package com.dfbz.entity;
import org.apache.solr.client.solrj.beans.Field;

public class Goods {

    @Field("id")
    private String id;
    @Field
    private String name;
    @Field
    private String title;
    @Field
    private Double price;
    @Field
    private String pic;
}
package com.dfbz.solr;

import com.dfbz.entity.Goods;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class Demo1 {

    private HttpSolrServer solrServer = new HttpSolrServer("http://localhost:8983/solr/collection1");

    @Test
    public void saveOrUpdate() throws IOException, SolrServerException {
        Goods goods = new Goods();
        goods.setId("888");
        goods.setName("东标方准牌手机");
        goods.setTitle("东标方准牌手机,好吃不上火!");
        goods.setPrice(9999.99);

        //如果没有则添加,如果有则修改
        solrServer.addBean(goods);

        //提交事务
        solrServer.commit();
    }
}

注意:在solr中,添加和修改是同一个方法,如果id存在则修改,如果id不存在则添加
47.png

删除索引

根据id删除:

  • 创建HttpSolrServer对象,连接solr服务
  • 使用HttpSolrServer对象执行删除
  • 提交事务
/** 根据id删除索引 */
@Test
public void deleteById() throws Exception{
    solrServer.deleteById("888");
    // 提交事务
    solrServer.commit();
}

根据条件删除

  • 创建HttpSolrServer对象,连接solr服务
  • 使用HttpSolrServer对象,执行删除
  • 提交事务
//根据条件删除
@Test
public void deleteByQuery() throws IOException, SolrServerException {

    solrServer.deleteByQuery("title:手机");

    solrServer.commit();
}

查询索引

  • 创建HttpSolrServer对象,连接solr服务
  • 创建查询对象(SolrQuery),封装查询条件
  • 使用HttpSolrServer对象执行搜索,返回QueryResposne对象
  • 通过QueryResponse对象中获取查询的结果
  • 处理结果```java //条件查询 @Test public void query() throws IOException, SolrServerException { SolrQuery solrQuery = new SolrQuery(“title:商务”);

    QueryResponse response = solrServer.query(solrQuery);

    System.out.println(“数量: “ + response.getResults().getNumFound());

    List goodsList = response.getBeans(Goods.class); for (Goods goods : goodsList) {

      System.out.println(goods);
      System.out.println("-------------------");
    

    } } ```

48.png

查询步骤:

  • 创建HttpSolrServer对象,连接solr服务
  • 创建查询对象(SolrQuery),封装查询条件
  • 使用HttpSolrServer对象执行搜索,返回QueryResponse
  • 通过QueryResponse获取搜索结果
  • 通过QueryResponse获取高亮内容
  • 处理搜索结果及高亮内容```java //复杂条件查询 @Test public void query2() throws IOException, SolrServerException {

      SolrQuery solrQuery = new SolrQuery("title:手机");
    
      //添加过滤条件
      solrQuery.addFilterQuery("price:[1000 TO 9000]");
    
      //排序
      solrQuery.addSort("price", SolrQuery.ORDER.desc);
    
      //分页
      solrQuery.setStart(0);
      solrQuery.setRows(10);
    
      //设置查询域
      solrQuery.setFields("id,price,name,title");
    
      //开启高亮
      solrQuery.setHighlight(true);
    
      //高亮域
      solrQuery.addHighlightField("title");
      solrQuery.setHighlightSimplePre("<font color='red'>");
      solrQuery.setHighlightSimplePost("</font>");
    
    QueryResponse response = solrServer.query(solrQuery);

    System.out.println("查询到的条数: " + response.getResults().getNumFound());

    //获取查询数据
    List<Goods> goodsList = response.getBeans(Goods.class);

    //获取高亮数据
    Map<String, Map<String, List<String>>> high = response.getHighlighting();
    for (Goods goods : goodsList) {
        //根据id查询到对应高亮数据(map);查询title的值
        System.out.println("id: " + goods.getId() + " title: " + high.get(goods.getId()).get("title"));
        ;

    }
}


![57.png](https://cdn.nlark.com/yuque/0/2020/png/726163/1593755101929-ec34b063-6381-48b2-9097-6c09de4070c7.png#align=left&display=inline&height=308&margin=%5Bobject%20Object%5D&name=57.png&originHeight=308&originWidth=1391&size=164652&status=done&style=none&width=1391)

<a name="62b2c525"></a>
#### set复杂查询

```java
//set查询
@Test
public void query3() throws IOException, SolrServerException {
    SolrQuery solrQuery = new SolrQuery();
    //设置全局查询
    solrQuery.set("q","小米");

    //设置FilterQuery
    solrQuery.set("fq", "price:[0 TO 8000]");

    //设置起始页数
    solrQuery.set("start", 0);

    //设置页大小
    solrQuery.set("rows", 5);

    //设置排序规则
    solrQuery.set("sort", "price desc");

    //设置FieldList
    solrQuery.set("fl", "id,name,price");

    //设置默认域
       solrQuery.set("df", "keywords");

    //开启高亮
    solrQuery.setHighlight(true);

    //设置高亮域
    solrQuery.addHighlightField("title");

    //设置高亮域
    solrQuery.addHighlightField("name");

    //高亮前缀
    solrQuery.setHighlightSimplePre("<font color='red'>");

    //高亮后缀
    solrQuery.setHighlightSimplePost("</font>");

    //执行查询
    QueryResponse response = solrServer.query(solrQuery);

    System.out.println("记录数: " + response.getResults().getNumFound());

    List<Goods> goodsList = response.getBeans(Goods.class);
    System.out.println("查询数据: ");
    for (Goods goods : goodsList) {
        System.out.println(goods);
    }

    System.out.println("----------------------");
    System.out.println("高亮数据: ");
    Map<String, Map<String, List<String>>> high = response.getHighlighting();

    for (Goods goods : goodsList) {
        String name = high.get(goods.getId()).get("title").get(0);
        String title = high.get(goods.getId()).get("name").get(0);
        System.out.println("name: " + name + ";title: " + title);

    }


}

Solr搜索案例

需求:实现小米商城商品搜索功能
58.png

创建Maven项目

引入依赖:

<?xml version="1.0" encoding="UTF-8"?>

<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>
    <groupId>com.dfbz</groupId>
    <artifactId>Solr_02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-core</artifactId>
            <version>4.10.3</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>

        <!--jstl依赖库-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

导入资料
59.png

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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">


    <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:dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

dispatcher-servlet.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描controller-->
    <context:component-scan base-package="com.dfbz" />

    <!--配置静态资源放行-->
    <mvc:default-servlet-handler />

    <mvc:annotation-driven />

    <!-- 配置SOlrJ -->
    <bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
        <constructor-arg value="http://localhost:8983/solr/collection1"/>
    </bean>
</beans>

controller:

package com.dfbz.controller;

import com.dfbz.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    /**
     * 搜索商品
     * @param val:前端提交过来的参数
     * @param model
     * @return
     */
    @RequestMapping("/search")
    public String search(String val, Model model){

        model.addAttribute("goodsList",goodsService.search(val));

        return "/list.jsp";

    }

}

service:

package com.dfbz.service;

import com.dfbz.entity.Goods;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class GoodsService {

    //注入solrService
    @Autowired
    private SolrServer solrServer;

    public List<Goods> search(String val) {
        try {
            SolrQuery solrQuery = new SolrQuery();
            //查询复制域
            solrQuery.setQuery("keywords:" + val);

            //起始索引
            solrQuery.setStart(0);

            //页大小
            solrQuery.setRows(20);

            //开启高亮
            solrQuery.setHighlight(true);

            //添加高亮域
            solrQuery.addHighlightField("title");
            solrQuery.addHighlightField("name");

            //前缀
            solrQuery.setHighlightSimplePre("<font color='red'>");

            //后缀
            solrQuery.setHighlightSimplePost("</font>");

            QueryResponse response = solrServer.query(solrQuery);

            List<Goods> goodsList = response.getBeans(Goods.class);

            //获取高亮数据
            Map<String, Map<String, List<String>>> high = response.getHighlighting();

            for (Goods goods : goodsList) {

                if(high.get(goods.getId()).get("name")!=null){
                    //将查询到的数据换成高亮数据
                    String name = high.get(goods.getId()).get("name").get(0);
                    goods.setName(name);
                }
                if(high.get(goods.getId()).get("title")!=null){
                    String title = high.get(goods.getId()).get("title").get(0);
                    //将查询到的数据换成高亮数据
                    goods.setTitle(title);
                }

            }

            return goodsList;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

测试:

package com.dfbz.solr;

import com.dfbz.entity.Goods;
import com.dfbz.service.GoodsService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:dispatcher-servlet.xml")
public class Demo1 {

    @Autowired
    private GoodsService goodsService;

    @Test
    public void test1(){

        List<Goods> goodsList = goodsService.search("手机");

        for (Goods goods : goodsList) {
            System.out.println(goods);
        }
    }

}

60.png
标签库:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

浏览器访问搜索测试:

61.png