zoukankan      html  css  js  c++  java
  • Solr全文检索服务器

    Solr讲义

    全文检索服务器

     

    1 Solr简介 3

    1.1 Solr是什么 3

    1.2 Solr能做什么 3

    1.3 为什么需要Solr 3

    1.4 Solr下载路径 4

    1.5 Solr目录结构说明 4

    2 入门示例 5

    2.1 需求 5

    2.2 配置步骤说明 5

    2.3 配置步骤 5

    2.4 第一部分:配置Solr服务器 5

    2.4.1 第一步:解压一个Tomcat 5

    2.4.2 第二步:部署Solr服务到Tomcat 5

    2.4.3 第三步:添加Solr运行依赖的jar 6

    2.5 第二部分:配置SolrHome 6

    2.5.1 第一步:拷贝到本地,修改名称为SolrHome。(见名知意) 7

    2.5.2 第二步:配置SolrCore 7

    2.6 第三部分:在Solr服务器中加载SolrHome 9

    2.6.1 第一步:修改web.xml加载SolrHome 9

    2.6.2 第二步:启动Tomcat测试 10

    2.7 第四部分:创建java程序访问solr服务器 10

    2.7.1 第一步:创建项目,导入jar 11

    2.7.2 第二步:创建索引 11

    2.7.3 第三步:搜索索引 19

    3 solr管理控制台 21

    3.1 查询界面说明 21

    3.2 安装DataImport插件 24

    3.2.1 Dataimport插件说明 24

    3.2.2 安装步骤 25

    3.3 Analyzer分析器,配置中文分词器 27

    3.3.1 Solr自带分词器的缺陷 27

    3.3.2 Solr配置中文分析器 27

    4 Solr案例实战 30

    4.1 需求 30

    4.2 分析 30

    4.2.1 UI分析 30

    4.2.2 架构分析 31

    4.3 环境准备 31

    4.4 功能开发 32

    4.4.1 第一步:创建web工程,导入jar 32

    4.4.2 第二步:代码实现 33

    4.4.3 第三步:Spring整合SolrSpringmvc 40

    4.5 启动web应用程序,测试 43

    4.5.1 注意事项 43

    4.5.2 修改Solr服务器的Tomcat的端口 43

    4.5.3 修改Springmvc.xml 43

    4.5.4 访问搜索页面 44

    1 Solr简介

    1.1 Solr是什么

    Solr是一个基于全文检索的企业级应用服务器。

    全文检索:可以输入一段文字,通过分词检索数据!!(复习)

    应用服务器:它是单独的服务。

    1.2 Solr能做什么

    它就是用于做全文搜索。

    1.3 为什么需要Solr

    问题:我们已经学过Lucene,为什么还要学习solr?

    答:Lucene是一个工具包,不能单独运行,需要导入到java代码中。

    Solr可以独立运行在tomcat容器中,通过http协议,以接口的方式对外提供服务,java代码只需要专注于业务的处理就可以。

    wps1

    1.4 Solr下载路径

    http://archive.apache.org/dist/lucene/solr/

    solr是基于lucene实现的,和Lucene同步更新。

    1.5 Solr目录结构说明

    下载solr-4.10.3.zip并解压:

    wps2

    bin:solr的运行脚本

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

    dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。

    docs:solr的API文档

    example:solr工程的例子目录:

    licenses:solr相关的一些许可信息

    2 入门示例

    2.1 需求

    使用Solr实现电商网站的商品搜索功能。

    2.2 配置步骤说明

    (1)配置Solr服务器。

    (2)配置SolrHome。(Solr服务的主目录,磁盘)

    (3)在Solr服务器中加载SolrHome。

    (4)java程序访问Solr服务器,实现全文搜索。

    2.3 配置步骤

    2.4 第一部分配置Solr服务器

    --说明:Solr可以独立运行,需要servlet容器加载它。本文使用tomcat。

    2.4.1 第一步:解压一个Tomcat

    解压一个新的Tomcat,专门用来加载Solr。

    wps3

    2.4.2 第二步:部署Solr服务到Tomcat中

    --在Solr的下载包中,提供了Solr的war包程序。(空的war包程序)

    wps4

    --拷贝solr.war到Tomcat的webapp目录下。并解压

    wps5

    2.4.3 第三步:添加Solr运行依赖的jar包

    --在Solr的下载包中,提供Solr服务器运行所依赖的jar包。

    wps6

    (1)拷贝/example/lib/ext下的所有包,到solr应用的lib目录中

    wps7

    (2)拷贝/example/resource/log4j.properties,到solr应用的classes目录下。

    --前提:先在/WEB-INF/目录下,创建classes目录。

    wps8

    2.5 第二部分配置SolrHome

    --说明:Solr的下载包中,提供了标准的SolrHome配置。

    wps9

    2.5.1 第一步:拷贝到本地,修改名称为SolrHome。(见名知意)

    wps10

    2.5.1.1 SolrHome说明

    --SolrHome目录结构:

    wps11

    (1)SolrHome是Solr配置搜索服务的主目录。

    (2)collection1称为Solr服务的一个实例(solrCore)。

    (3)一个solr实例对应一个索引库。

    (4)Solr可以同时配置多个实例。以便为不同的java程序提供搜索服务。

    配置solr服务,就是在配置solr实例。

    2.5.2 第二步:配置SolrCore
    2.5.2.1 Step1:配置SolrCore实例的名称

    --说明:每一个实例都有自己的名称。在core.properties文件中配置

    wps12

    --在这里,我们将其修改为:soreCore0719

    wps13

    2.5.2.2 Step2:配置SolrCore所需的jar依赖

    --说明:Solr下载包中,提供SolrCore所需要的所有jar依赖。

    wps14

    (1)在SolrHome同级目录下,创建depJar文件夹。(目的:方便管理jar依赖)

    wps15

    (2)拷贝contrib、dist两个目录到depJar目录下。

    wps16

    (3)修改/collection1/conf目录下的solrconfig.xml,加载jar包

    --说明:solr是通过<lib>标签,来加载运行所需要的jar包的。

    wps17

    (4)配置索引库目录

    --说明:solr是通过<dataDir>标签,来指定索引库的目录的。

    wps18

    --默认路径是在SolrCore目录下,跟conf目录同级。首次加载时,将自动创建。

    wps19

    本课程就使用该默认路径。

    2.6 第三部分:在Solr服务器中加载SolrHome

    2.6.1 第一步:修改web.xml加载SolrHome

    --在solr的应用中,是通过web.xml来加载SolrHome的。

    wps20

    --说明:在这里是通过修改<env-entry>标签,来加载SolrHome的。

    wps21

    2.6.2 第二步:启动Tomcat测试

    --访问地址   http://localhost:8080/solr

    wps22

    --solr服务器配置成功!!!

    2.7 第四部分:创建java程序访问solr服务器

    --前提:创建好了数据库。(导入products-solr.sql文件即可)

    wps23

    --配置步骤说明:

    (1)创建项目。

    (2)创建索引

    (3)搜索索引

    2.7.1 第一步:创建项目,导入jar包

    --导包说明:

    SolrJ核心包     /solr-4.10.3/dist/solr-solrj-4.10.3.jar

    SolrJ依赖包     /solr-4.10.3/dist/solrj-lib下的所有包

    日志依赖包     /solr-4.10.3/example/lib/ext目录下的所有jar包

    JDBC驱动包     mysql-connector-java-5.1.10-bin.jar

    --拷贝log4j.properties到src目录下。(或者创建一个Source Folder)

    --项目结构:

    wps24

    2.7.2 第二步:创建索引

    --步骤说明。(复习回顾)

    (1)采集数据。

    (2)将数据转换成Solr文档。

    (3)连接solr服务器,将文档写入索引库。

    2.7.2.1 Step1:采集数据

    --需求采集的字段说明:

    参与搜索的字段:名称、价格、商品类别、描述信息

    参与结果展示的字段:商品id、图片、

    (1)创建Product类

    public class Product {

    private Integer pid;

    private String name;

    private String catalog_name;

    private double price;

    private String description;

    private String picture;

    // 补全getset方法

    }

    (2)创建ProductDao类

    package cn.gzsxt.solr.dao;

    import java.sql.Connection;

    import java.sql.DriverManager;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.SQLException;

    import java.util.ArrayList;

    import java.util.List;

    import cn.gzsxt.solr.pojo.Product;

    public class ProductDao {

    private Connection connection;

    private PreparedStatement pst;  

    private ResultSet rs;

    /**

    * 采集数据,查询所有商品

    * @return

    */

    public List<Product> getAllProducts() {

    List<Product> products = new ArrayList<>();

    try {

    //1、加载驱动

    Class.forName("com.mysql.jdbc.Driver");

    //2、获取Connection连接

    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/solr", "root", "gzsxt");

    //3、获取PreparedStatement,执行预编译

    pst = connection.prepareStatement("select pid,name, catalog_name,price,description,picture from products");

    //4、执行sql搜索

    rs = pst.executeQuery();

    Product p = null;

    while(rs.next()){

    p = new Product();

    p.setPid(rs.getInt("pid"));

    p.setName(rs.getString("name"));

    p.setPrice(rs.getFloat("price"));

    p.setPicture(rs.getString("picture"));

    p.setDescription(rs.getString("description"));

    p.setCatalog_name(rs.getString("catalog_name"));

    products.add(p);

    }

    } catch (Exception e) {

    e.printStackTrace();

    }finally {

    if(null!=rs){

    try {

    rs.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    if(null!=pst){

    try {

    pst.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    if(null!=connection){

    try {

    connection.close();

    } catch (SQLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    return products;

    }

    }

    (3)创建一个测试类ProductDaoTest

    --导入junit类库。(快捷键ctrl+1)

    package cn.gzsxt.solr.test;

    import org.junit.Test;

    import cn.gzsxt.solr.dao.ProductDao;

    public class ProductDaoTest {

    @Test

    public void getAllProducts(){

    ProductDao dao = new ProductDao();

    System.out.println(dao.getAllProducts());

    }

    }

    --测试结果,采集数据成功!!!

    wps25

    2.7.2.2 Step2:将数据转换成Solr文档SolrInputDocument

    --说明:solr是通过SolrInputDocument来封装数据的。部分源码如下:

    public SolrInputDocument(Map fields){

    _documentBoost = 1.0F;

    _fields = fields;

    }

    public void addField(String name, Object value){

            addField(name, value, 1.0F);

    }

    问题:我们在Lucene中知道,域有三大属性,在创建文档的时候指定。而Solr的源码中,只是用一个Map集合来封装域的信息。那域的三大属性怎么定义呢?

    答:Solr是通过一个配置文件schema.xml,事先定义域的信息的。

    2.7.2.2.1 Solr域的说明

    --通过<field>标签定义域的名称等信息

    wps26

    name属性:域的名称

    type属性: 域的类型(<FieldType>标签,加载了分词器,指定了分词属性)

    indexed属性:是否索引

    stored属性:是否存储

    multiValued属性:是否支持多个值

    --通过<fieldType>标签,定义域的类型信息

    wps27

    name属性:域类型的名称

    class属性:指定域类型的solr类型。

    <analyzer>:指定分词器。

    <analyzer  type=”index”>:表示在创建索引时,对域做分词处理。

    <analyzer  type=”query”>:表示在检索索引时,对域做分词处理。

    <tokenizer>标签:指定分词器

    <filter>标签:指定过滤器

    2.7.2.2.2 Solr域的特点

    (1)、Solr的域必须先定义,后使用。(否则报错:unknown fieldName)

    (2)、定义solr域的时候,必须指定是否索引、是否存储这两个属性。<field>

    (3)、定义solr域的时候,必须指定域的类型<fieldType>:

    因为域的类型确定了这个域在索引、搜索两个阶段的分词属性。

    <field>标签: 来指定索引、存储两个属性

    <fieldType>标签:来指定分词属性

    (4)、每一个文档中,必须包含id这个域,它的值标记文档的唯一性。

    wps28

    2.7.2.2.3 配置Solr业务域

    --商品各字段属性说明

    Tokened

    Indexed

    Stored

    商品的id

    N

    Y

    Y

    商品的名称

    Y

    Y

    Y

    商品的类别

    N

    Y

    Y

    商品的价格

    Y

    Y

    Y

    商品的图片

    N

    N

    Y

    商品描述信息

    Y

    Y

    N

    --修改schema.xml,添加如下配置。(id域不用配置,直接使用solr的id域)

    <!--product-->

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

    multiValued="false" />

    <field name="product_name" type="text_general" indexed="true" stored="true"/>

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

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

    <field name="product_description" type="text_general" indexed="true" stored="false" />

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

    2.7.2.2.4 修改ProductDao,新增getDocuments方法

    /**

    * 将采集到的商品数据,转换成solr文档类型

    * @param products

    * @return

    */

    public List<SolrInputDocument> getDocuments(List<Product> products){

    List<SolrInputDocument> docs = new ArrayList<>();

    SolrInputDocument doc = null;

    for (Product product : products) {

    doc = new SolrInputDocument();

    doc.addField("id", product.getPid());

    doc.addField("product_name", product.getName());

    doc.addField("product_price", product.getPrice());

    doc.addField("product_catalog_name", product.getCatalog_name());

    doc.addField("product_description", product.getDescription());

    doc.addField("product_picture", product.getPicture());

    docs.add(doc);

    }

    return docs;

    }

    2.7.2.3 Step3:连接Solr服务器,创建索引

    --前提:已经启动了Tomcat,加载了Solr服务器。(前面给过schema.xml,需要重写启动Tomcat)

    --修改ProductDaoTest类,新增createIndex方法

    @Test

    public void createIndex(){

    // 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

    // 参数:solr服务器的访问地址

    HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/solrCore0719");

    // 2、 通过HttpSolrServer对象将SolrInputDocument添加到索引库。

    ProductDao dao = new ProductDao();

    try {

    server.add(dao.getDocuments(dao.getAllProducts()));

    // 3、 提交。

    server.commit();

    System.out.println("创建索引库成功!!!");

    } catch (SolrServerException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    2.7.2.4 Step4:访问Solr主界面,在Query选项下测试

    wps29

    --创建索引库成功!!!

    2.7.3 第三步:搜索索引

    --修改ProductDaoTest类型,新增一个查询方法

    @Test

    public void queryIndex() throws Exception {

    // 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

    // 参数:solr服务器的访问地址

    HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/solrCore0719");

    // 创建SolrQuery对象

    SolrQuery query = new SolrQuery();

    // 设置查询条件,参考主界面

    query.set("q", "*:*");

    // 调用server的查询方法,查询索引库

    QueryResponse response = server.query(query);

    // 查询结果

    SolrDocumentList results = response.getResults();

    // 查询结果总数

    long cnt = results.getNumFound();

    System.out.println("查询结果总数:" + cnt);

    System.out.println("--------------------分隔符-------------------");

    for (SolrDocument solrDocument : results) {

    System.out.println("商品id:"+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("----------------------------------------");

    }

    }

    --查询结果,非常成功!!!

    wps30

    3 solr管理控制台

    3.1 查询界面说明

    wps31

    (1) q - 查询关键字,必须,如果查询所有文档时,使用*:*。

    wps32

    (2) fq - (filter query)过虑查询,可以有多个。如:价格10到50的记录。

    wps33

    (3) sort - 排序,格式:sort=<field name>+<desc|asc>。如:按价格升序

    wps34

    (4) start - 分页显示使用,开始记录下标,从0开始

    wps35

    (5) rows - 指定返回结果最多有多少条记录,配合start来实现分页。

    wps36

    (6) fl - 指定返回那些字段内容,用逗号或空格分隔多个。

    wps37

    (7) df-指定一个默认搜索的Field

    wps38

    (8) wt - (writer type)指定输出格式,默认json格式。

    wps39

    3.1.1 对照界面,实现复杂查询

    --修改ProductDaoTest类型,新增动态查询方法

    @Test

    public void queryDynamic(){

    //1、连接solr服务器

    HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/solrCore0719");

    //2、创建查询对象,封装查询条件

    SolrQuery query = new SolrQuery();

    //设置默认搜索的域

    query.set("df", "product_name");

    //参考管理界面中的 "q"标签,封装查询的关键词

    query.set("q", "音乐盒");

    //添加价格过滤

    query.addFilterQuery("product_price:[10 TO 50]");

    //添加类别过滤

    query.addFilterQuery("product_catalog_name:幽默杂货");

    //设置排序  价格升序

    query.set("sort","product_price asc");

    //设置分页信息  第二页 每页10条   start=(page-1)*pageSize

    query.set("start", 10);

    query.set("rows",10);

    //设置要查询字段

    query.set("fl", "id,product_name,product_price");

    //3、执行查询

    try {

    QueryResponse response = server.query(query);

    //获取查询的响应码

    int status = response.getStatus();

    System.out.println("响应码:"+status);

    if(0==status){

    SolrDocumentList solrDocumentList = response.getResults();

    long numFound = solrDocumentList.getNumFound();

    System.out.println("共查询到"+numFound+"条满足条件的数据!");

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

    for (SolrDocument s : solrDocumentList) {

    System.out.println("商品的id:"+s.get("id"));

    System.out.println("商品的名称:"+s.get("product_name"));

    System.out.println("商品的价格:"+s.get("product_price"));

    System.out.println("商品的图片:"+s.get("product_picture"));

    System.out.println("商品的类别名称:"+s.get("product_catalog_name"));

    System.out.println("商品的描述:"+s.get("product_decsription"));

    System.out.println("-----------分隔符---------------");

    }

    }

    } catch (SolrServerException e) {

    e.printStackTrace();

    }

    }

    --测试结果:非常成功!!!(对比管理界面查询结果)

    wps40

    3.2 安装DataImport插件

    3.2.1 Dataimport插件说明

    --好处:可以在管理界面直接从数据库导入数据到索引库。(即:一个插件解决入门示例中,创建索引的全部操作)

    wps41

    3.2.2 安装步骤
    3.2.2.1 第一步:添加jar依赖

    (1)将/solr-4.10.3/dist/solr-dataimporthandler-4.10.3.jar拷贝到

    /depJar/contrib/dataimporthandler/lib目录下

    wps42

    (2)、将jdbc驱动包拷贝到   /depJar/contrib/db/lib 目录下

    wps43

    (3)、在solrconfig.xml文件中,加载这两个jar依赖

    <lib dir="F:/depJar/contrib/dataimporthandler/lib/" regex=".*.jar" />

    <lib dir="F:/depJar/contrib/db/lib/" regex=".*.jar" />

    3.2.2.2 第二步:配置数据库表solr域的映射关系

    --在solr实例的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="gzsxt"/>  

    <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" 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>

    3.2.2.3 第三步:创建dataimport处理器

    --说明:Solr是在solrconfig.xml文件中,通过<requestHandler>标签定义各类请求处理器

    --修改solrconfig.xml,添加如下配置。(加载data-config.xml映射文件)

    <requestHandler name="/dataimport"

    class="org.apache.solr.handler.dataimport.DataImportHandler">

               <lst name="defaults">

               <str name="config">data-config.xml</str>

               </lst>

      </requestHandler>

    3.2.2.4 第四步:重启tomcat,在管理界面测试

    --测试清空索引库,成功!!!

    wps44

    --测试重新导入数据,成功!!!

    wps45

    3.3 Analyzer分析器,配置中文分词器

    3.3.1 Solr自带分词器的缺陷

    --solr跟Lucene一样,提供了很多分析器。可以在Analyzer选型下测试分词效果。

    wps46

    --测试发现:所以的分词器,对中文支持都不友好。

    解决办法:配置中文分词器。

    3.3.2 Solr配置中文分析器
    3.3.2.1 中文分析器选择

    选择IK中文分词器。

    3.3.2.2 配置步骤
    3.3.2.2.1 第一步:添加IkAnalyze的jar依赖

    --把IKAnalyzer2012FF_u1.jar添加到solr/WEB-INF/lib目录下。

    3.3.2.2.2 第二步:加载IkAnalyzer的核心配置文件

    --拷贝IkAnalyzer的配置文件到solr/WEB-INF/classes目录

    wps47

    3.3.2.2.3 第三步:创建中文分词器

    --在schema.xml中自定义一个FieldType,指定中文分词器IKAnalyzer。

    <!-- IKAnalyzer-->

        <fieldType name="text_ik" class="solr.TextField">

                 <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

        </fieldType>

    3.3.2.3 测试中文分词器
    3.3.2.3.1 第一步:重启tomcat
    3.3.2.3.2 第二步:在analysis选项卡下,测试分词效果。成功!!!

    wps48

    3.3.3 改造业务域,使用IK做分词器

    --修改schem.xml文件,修改需要分词的域的fieldType类型

    我们只需要修改product_name、product_description两个业务域即可。

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

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

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

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

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

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

    --重启tomcat即可。

    4 Solr案例实战

    4.1 需求

    使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能。

    界面如下:

    wps49

    4.2 分析

    开发人员需要的文档:静态页面(根据UI设计由美工给出)、数据库设计、原型设计

    4.2.1 UI分析

    wps50

    4.2.2 架构分析

    wps51

    架构分为:

    (1)、solr服务器。(已经做完,同入门示例)

    (2)、自己开发的应用(重点)

    (3)、数据库mysql

    自己开发的应用

    Controller      负责和前端页面进行请求和响应的交互

    Service 封装查询条件,调用dao。

    Dao 搜索索引库,返回搜索结果。

    4.3 环境准备

    Solr:4.10.3

    Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下)

    Ide环境:Eclipse

    Web服务器(servlet容器):Tomcat 7X

    4.4 功能开发

    4.4.1 第一步:创建web工程,导入jar包

    wps52

    --导入的jar包说明:

    Solrj的包

    Solr服务的日志包

    Spring的包(包含springmvc)

    核心包  4个 core 、bean、context、expresstion

    注解包  aop

    Web包  web、webmvc

    Commons日志包  common-logging

    Jstl包

    --导入静态资源和jsp页面说明:

    静态资源放在webapp目录下,jsp页面放到/WEB-INF/目录下

    4.4.2 第二步:Spring整合Solr、Springmvc
    4.4.2.1 创建springmvc.xml

    在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="cn.gzsxt" />

    <!-- 配置注解驱动 -->

    <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>

    <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">

    <constructor-arg value="http://localhost:8080/solr/solrCore0719"></constructor-arg>

    </bean>

    </beans>

    4.4.2.2 创建Web.xml

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

    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">

    <display-name>JD0719</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>/</url-pattern>

    </servlet-mapping>

    <filter>

    <filter-name>Character 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>Character Encoding</filter-name>

    <url-pattern>*.action</url-pattern>

    </filter-mapping>

    </web-app>

    4.4.3 第三步:整合测试
    4.4.3.1 需求:

    访问搜索页面。

    4.4.3.2 创建PageController类

    package cn.gzsxt.solr.controller;

    import org.springframework.stereotype.Controller;

    import org.springframework.web.bind.annotation.PathVariable;

    import org.springframework.web.bind.annotation.RequestMapping;

    @Controller

    public class PageController {

    @RequestMapping(value="/{page}")

    public String showPage(@PathVariable("page")String page){

    return page;

    }

    }

    4.4.3.3 注意事项

    (1)Solr服务器要先开启。

    (2)Solr服务器部署的Tomcat和本web应用的部署的Tomcat不是同一个。

    (3)要同时启动两个Tomcat,要注意端口冲突问题。

    4.4.3.4 修改Solr服务器的Tomcat的端口

    --在server.xml文件中,修改端口

    --tomcat端口说明:

    8005:关机端口

    8080:默认服务端口

    8009:请求转向端口。

    --注意:这三个端口都需要修改。不然启动会冲突

    本次课程中,将solr的tomcat端口,修改为8888.

    4.4.3.5 修改Springmvc.xml

    --修改Solr服务的端口

    <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">

    <constructor-arg value="http://localhost:8888/solr/solrCore0719"></constructor-arg>

    </bean>

    4.4.3.6 访问搜索页面

    地址:http://localhost:8080/solr-demo-02-jd/product_list.action

    wps53

    整合成功!!!

    4.4.4 第四步:搜索功能实现

    分析代码结构:

    请求路径

    list.action

    请求方式

    POST

    请求参数

    queryString、catalog_name、price、curPage、sort(共5个)

    返回结果

    定义Product 以及ProductModel

    4.4.4.1 Pojo
    4.4.4.1.1 分析

    结合查询界面,分析得出:

    --需要一个商品的pojo(Product),存放商品信息

    --需要一个包装pojo(ResultModel),它包括商品列表信息、商品分页信息

    4.4.4.1.2 创建Product类

    public class Product {

    // 商品编号

    private String pid;

    // 商品名称

    private String name;

    // 商品分类名称

    private String catalog_name;

    // 价格

    private double price;

    // 商品描述

    private String description;

    // 图片名称

    private String picture;

    }

    4.4.4.1.3 创建ResultModel类

    public class ResultModel {

    private List<Product> productList;

    // 商品总数

    private Long recordCount;

    // 总页数

    private int pageCount;

    // 当前页

    private int currentPage;

    }

    4.4.4.2 Dao
    4.4.4.2.1 功能

    接收service层传递过来的参数,根据参数查询索引库,返回查询结果。

    4.4.4.2.2 创建ProductDao接口,定义一个查询方法

    public interface ProductDao {

    //查询商品信息,包括分页信息

    public ResultModel queryProduct(SolrQuery query) throws Exception;

    }

    4.4.4.2.3 创建ProductDaoImpl,重新改查询方法

    package cn.gzsxt.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.impl.HttpSolrServer;

    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 cn.gzsxt.bean.Product;

    import cn.gzsxt.bean.ResultModel;

    import cn.gzsxt.dao.ProductDao;

    @Repository

    public class ProductDaoImpl implements ProductDao {

    @Autowired

    private HttpSolrServer server;

    @Override

    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 = null;

    // 高亮信息

    Map<String, Map<String, List<String>>> highlighting = response

    .getHighlighting();

    for (SolrDocument solrDocument : documentList) {

    product = new Product();

    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;

    }

    }

    4.4.4.3 Service
    4.4.4.3.1 功能分析

    接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。

    接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。

    4.4.4.3.2 创建ProductService接口,定义一个查询方法

    public interface ProductService {

    public ResultModel queryProduct(String queryString, String cataName,

    String price, String sort, Integer curPage) throws Exception;

    }

    4.4.4.3.3 创建ProductServiceImpl类,重写改查询方法

    package cn.gzsxt.service.impl;

    import org.apache.solr.client.solrj.SolrQuery;

    import org.apache.solr.client.solrj.SolrQuery.ORDER;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Service;

    import cn.gzsxt.dao.ProductDao;

    import cn.gzsxt.service.ProductService;

    import cn.gzsxt.vo.ResultModel;

    @Service

    public class ProductServiceImpl implements ProductService {

    @Autowired

    private ProductDao productDao;

    @Override

    public ResultModel queryProduct(String queryString, String cataName,

    String price, String sort, Integer curPage) throws Exception {

    //封装查询条件

    SolrQuery query = new SolrQuery();

    //判断查询条件是否为空

    if(!"".equals(queryString)&& null != queryString){

    query.setQuery(queryString);

    }else{

    query.setQuery("*:*");

    }

    //判断过滤条件是否为空

    if(!"".equals(cataName)&& null !=cataName){

    query.addFilterQuery("product_catalog_name:"+cataName);

    }

    //判断商品价格是否为空

    if(!"".equals(price) && null != price){

    String[] prices = price.split("-");

    if(prices.length == 2){

    query.addFilterQuery("product_price:["+prices[0]+" TO "+prices[1]+"]");

    }

    }

    //设置排序

    if("1".equals(sort)){

    query.setSort("product_price", ORDER.desc);

    }else {

    query.setSort("product_price", ORDER.asc);

    }

    //设置分页信息

    if(null == curPage){

    curPage = 1;

    }

    query.setStart((curPage-1)*20);

    query.setRows(20);  //每页20条数据

    //设置默认搜索域

    query.set("df","product_name");

    query.setHighlight(true);

    query.addHighlightField("product_name");

    query.setHighlightSimplePre("<font style="color:red">");

    query.setHighlightSimplePost("</font>");

    ResultModel result = productDao.queryProduct(query);

    result.setCurrentPage(curPage);

    // 总页数 = 总数量 / 每页数据条数  结果向上取整

    double ceil = Math.ceil(result.getRecordCount().doubleValue()/20);

    result.setPageCount((int)ceil);

    return result;

    }

    }

    4.4.4.4 Controller
    4.4.4.4.1 创建ProductController类,定义查询接口

    package cn.gzsxt.controller;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Controller;

    import org.springframework.ui.ModelMap;

    import org.springframework.web.bind.annotation.RequestMapping;

    import cn.gzsxt.service.ProductService;

    import cn.gzsxt.vo.ResultModel;

    @Controller

    public class ProductController {

    @Autowired

    private ProductService productService;

    @RequestMapping("/list.action")

    public String queryProduct(String queryString, String catalog_name,

    String price, String sort, Integer curPage, ModelMap model)

    throws Exception {

    ResultModel resultModel = productService.queryProduct(queryString, catalog_name,

    price, sort, curPage);

    model.addAttribute("result", resultModel);

    model.addAttribute("queryString", queryString);

    model.addAttribute("catalog_name", catalog_name);

    model.addAttribute("price", price);

    model.addAttribute("sort", sort);

    model.addAttribute("page", curPage);

    return "product_list";

    }

    }

    4.4.4.5 测试搜索功能

    地址:http://localhost:8080/solr-demo-02-jd/list.action

    wps54

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/meizhoulqp/p/11216693.html
Copyright © 2011-2022 走看看