Solr是一个基于全文检索的企业级应用服务器。
全文检索:可以输入一段文字,通过分词检索数据!!(复习)
应用服务器:它是单独的服务。
它就是用于做全文搜索。
问题:我们已经学过Lucene,为什么还要学习solr?
答:Lucene是一个工具包,不能单独运行,需要导入到java代码中。
Solr可以独立运行在tomcat容器中,通过http协议,以接口的方式对外提供服务,java代码只需要专注于业务的处理就可以。
http://archive.apache.org/dist/lucene/solr/
solr是基于lucene实现的,和Lucene同步更新。
下载solr-4.10.3.zip并解压:
bin:solr的运行脚本
contrib:solr的一些扩展jar包,用于增强solr的功能。
dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。
docs:solr的API文档
example:solr工程的例子目录:
licenses:solr相关的一些许可信息
使用Solr实现电商网站的商品搜索功能。
(1)配置Solr服务器。
(2)配置SolrHome。(Solr服务的主目录,磁盘)
(3)在Solr服务器中加载SolrHome。
(4)java程序访问Solr服务器,实现全文搜索。
--说明:Solr可以独立运行,需要servlet容器加载它。本文使用tomcat。
解压一个新的Tomcat,专门用来加载Solr。
--在Solr的下载包中,提供了Solr的war包程序。(空的war包程序)
--拷贝solr.war到Tomcat的webapp目录下。并解压
--在Solr的下载包中,提供Solr服务器运行所依赖的jar包。
(1)拷贝/example/lib/ext下的所有包,到solr应用的lib目录中
(2)拷贝/example/resource/log4j.properties,到solr应用的classes目录下。
--前提:先在/WEB-INF/目录下,创建classes目录。
--说明:Solr的下载包中,提供了标准的SolrHome配置。
--SolrHome目录结构:
(1)SolrHome是Solr配置搜索服务的主目录。
(2)collection1称为Solr服务的一个实例(solrCore)。
(3)一个solr实例对应一个索引库。
(4)Solr可以同时配置多个实例。以便为不同的java程序提供搜索服务。
配置solr服务,就是在配置solr实例。
--说明:每一个实例都有自己的名称。在core.properties文件中配置
--在这里,我们将其修改为:soreCore0719
--说明:Solr下载包中,提供SolrCore所需要的所有jar依赖。
(1)在SolrHome同级目录下,创建depJar文件夹。(目的:但有多个solrhome时,方便管理jar依赖)
(2)拷贝contrib、dist两个目录到depJar目录下。
(3)修改/collection1/conf目录下的solrconfig.xml,加载jar包
--说明:solr是通过<lib>标签,来加载运行所需要的jar包的。
(4)配置索引库目录
--说明:solr是通过<dataDir>标签,来指定索引库的目录的。
--默认路径是在SolrCore目录下,跟conf目录同级。首次加载时,将自动创建。
本课程就使用该默认路径。
--在solr的应用中,是通过web.xml来加载SolrHome的。
--说明:在这里是通过修改<env-entry>标签,来加载SolrHome的。
--访问地址 http://localhost:8080/solr
--solr服务器配置成功!!!
--前提:创建好了数据库。(导入products-solr.sql文件即可)
--配置步骤说明:
(1)创建项目。
(2)创建索引
(3)搜索索引
--导包说明:
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)
--项目结构:
--步骤说明。(复习回顾)
(1)采集数据。
(2)将数据转换成Solr文档。
(3)连接solr服务器,将文档写入索引库。
--需求采集的字段说明:
参与搜索的字段:名称、价格、商品类别、描述信息
参与结果展示的字段:商品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;
// 补全get、set方法
}
(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());
}
}
--测试结果,采集数据成功!!!
--说明: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,事先定义域的信息的。
--通过<field>标签定义域的名称等信息
name属性:域的名称
type属性: 域的类型(<FieldType>标签,加载了分词器,指定了分词属性)
indexed属性:是否索引
stored属性:是否存储
multiValued属性:是否支持多个值
--通过<fieldType>标签,定义域的类型信息
name属性:域类型的名称
class属性:指定域类型的solr类型。
<analyzer>:指定分词器。
<analyzer type=”index”>:表示在创建索引时,对域做分词处理。
<analyzer type=”query”>:表示在检索索引时,对域做分词处理。
<tokenizer>标签:指定分词器
<filter>标签:指定过滤器
(1)、Solr的域必须先定义,后使用。(否则报错:unknown fieldName)
(2)、定义solr域的时候,必须指定是否索引、是否存储这两个属性。<field>
(3)、定义solr域的时候,必须指定域的类型<fieldType>:
因为域的类型确定了这个域在索引、搜索两个阶段的分词属性。
<field>标签: 来指定索引、存储两个属性
<fieldType>标签:来指定分词属性
(4)、每一个文档中,必须包含id这个域,它的值标记文档的唯一性。
--商品各字段属性说明
域
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" />
/**
* 将采集到的商品数据,转换成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();
//这里的fieldnanme要同schema.xml文件配置的field标签中的name相同
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;
}
--前提:已经启动了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();
}
}
--创建索引库成功!!!
--修改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("----------------------------------------");
}
}
--查询结果,非常成功!!!
(1) q - 查询关键字,必须,如果查询所有文档时,使用*:*。
(2) fq - (filter query)过虑查询,可以有多个。如:价格10到50的记录。
(3) sort - 排序,格式:sort=<field name>+<desc|asc>。如:按价格升序
(4) start - 分页显示使用,开始记录下标,从0开始
(5) rows - 指定返回结果最多有多少条记录,配合start来实现分页。
(6) fl - 指定返回那些字段内容,用逗号或空格分隔多个。
(7) df-指定一个默认搜索的Field
(8) wt - (writer type)指定输出格式,默认json格式。
--修改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();
}
}
--测试结果:非常成功!!!(对比管理界面查询结果)
--好处:可以在管理界面直接从数据库导入数据到索引库。(即:一个插件解决入门示例中,创建索引的全部操作)
(1)将/solr-4.10.3/dist/solr-dataimporthandler-4.10.3.jar拷贝到
/depJar/contrib/dataimporthandler/lib目录下
(2)、将jdbc驱动包拷贝到 /depJar/contrib/db/lib 目录下
(3)、在SolrHome中的实例的conf文件夹中的solrconfig.xml文件中,加载这两个jar依赖
<lib dir="F:/depJar/contrib/dataimporthandler/lib/" regex=".*\.jar" />
<lib dir="F:/depJar/contrib/db/lib/" regex=".*\.jar" />
--在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>
--说明: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>
--测试清空索引库,成功!!!
--测试重新导入数据,成功!!!
--solr跟Lucene一样,提供了很多分析器。可以在Analyzer选型下测试分词效果。
--测试发现:所以的分词器,对中文支持都不友好。
解决办法:配置中文分词器。
选择IK中文分词器。
--把IKAnalyzer2012FF_u1.jar添加到solr/WEB-INF/lib目录下。
--拷贝IkAnalyzer的配置文件到solr/WEB-INF/classes目录
--在schema.xml中自定义一个FieldType,指定中文分词器IKAnalyzer。
<!-- IKAnalyzer-->
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
--修改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即可。
使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能。
界面如下:
开发人员需要的文档:静态页面(根据UI设计由美工给出)、数据库设计、原型设计
架构分为:
(1)、solr服务器。(已经做完,同入门示例)
(2)、自己开发的应用(重点)
(3)、数据库mysql
自己开发的应用
Controller 负责和前端页面进行请求和响应的交互
Service 封装查询条件,调用dao。
Dao 搜索索引库,返回搜索结果。
Solr:4.10.3
Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下)
Ide环境:Eclipse
Web服务器(servlet容器):Tomcat 7X
--导入的jar包说明:
Solrj的包
Solr服务的日志包
Spring的包(包含springmvc)
核心包 4个 core 、bean、context、expresstion
注解包 aop
Web包 web、webmvc
Commons日志包 common-logging
Jstl包
--导入静态资源和jsp页面说明:
静态资源放在webapp目录下,jsp页面放到/WEB-INF/目录下
在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>
<?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>
访问搜索页面。
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;
}
}
(1)Solr服务器要先开启。
(2)Solr服务器部署的Tomcat和本web应用的部署的Tomcat不是同一个。
(3)要同时启动两个Tomcat,要注意端口冲突问题。
--在server.xml文件中,修改端口
--tomcat端口说明:
8005:关机端口
8080:默认服务端口
8009:请求转向端口。
--注意:这三个端口都需要修改。不然启动会冲突
本次课程中,将solr的tomcat端口,修改为8888.
--修改Solr服务的端口
<bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg value="http://localhost:8888/solr/solrCore0719"></constructor-arg>
</bean>
地址:http://localhost:8080/solr-demo-02-jd/product_list.action
整合成功!!!
分析代码结构:
请求路径
list.action
请求方式
POST
请求参数
queryString、catalog_name、price、curPage、sort(共5个)
返回结果
定义Product 以及ProductModel
结合查询界面,分析得出:
--需要一个商品的pojo(Product),存放商品信息
--需要一个包装pojo(ResultModel),它包括商品列表信息、商品分页信息
public class Product {
// 商品编号
private String pid;
// 商品名称
private String name;
// 商品分类名称
private String catalog_name;
// 价格
private double price;
// 商品描述
private String description;
// 图片名称
private String picture;
}
public class ResultModel {
private List<Product> productList;
// 商品总数
private Long recordCount;
// 总页数
private int pageCount;
// 当前页
private int currentPage;
}
接收service层传递过来的参数,根据参数查询索引库,返回查询结果。
public interface ProductDao {
//查询商品信息,包括分页信息
public ResultModel queryProduct(SolrQuery query) throws Exception;
}
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;
}
}
接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。
接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
public interface ProductService {
public ResultModel queryProduct(String queryString, String cataName,
String price, String sort, Integer curPage) throws Exception;
}
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;
}
}
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";
}
}
地址:http://localhost:8080/solr-demo-02-jd/list.action
转载于:https://www.cnblogs.com/wozibi/p/11256286.html
相关资源:数据结构—成绩单生成器