需求
使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能。
架构分为:
(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
功能开发
第一步:创建web工程,导入jar包
--导入的jar包说明:
Solrj的包
Solr服务的日志包
Spring的包(包含springmvc)
核心包4个 core 、bean、context、expresstion
注解包aop
Web包web、webmvc
Commons日志包 common-logging
Jstl包
--导入静态资源和jsp页面说明:
静态资源放在webapp目录下,jsp页面放到/WEB-INF/目录下
第二步:Spring整合Solr、Springmvc
创建springmvc.xml
在config包下,创建springmvc.xml文件
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 "> class="org.springframework.web.servlet.view.InternalResourceViewResolver">
创建Web.xml
"1.0" encoding="UTF-8"?>
第三步:整合测试
需求:
访问搜索页面。
创建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;
}
}
注意事项
(1)Solr服务器要先开启。
(2)Solr服务器部署的Tomcat和本web应用的部署的Tomcat不是同一个。
(3)要同时启动两个Tomcat,要注意端口冲突问题。
修改Solr服务器的Tomcat的端口
--在server.xml文件中,修改端口
--tomcat端口说明:
8005:关机端口
8080:默认服务端口
8009:请求转向端口。
--注意:这三个端口都需要修改。不然启动会冲突
本次课程中,将solr的tomcat端口,修改为8888.
修改Springmvc.xml
--修改Solr服务的端口
访问搜索页面
地址:http://localhost:8080/solr-demo-02-jd/product_list.action
整合成功!!!
第四步:搜索功能实现
分析代码结构:
请求路径list.action
请求方式POST
请求参数queryString、catalog_name、price、curPage、sort(共5个)
返回结果定义Product 以及ProductModel
Pojo
分析
结合查询界面,分析得出:
--需要一个商品的pojo(Product),存放商品信息
--需要一个包装pojo(ResultModel),它包括商品列表信息、商品分页信息
创建Product类
public class Product {
//商品编号
private String pid;
//商品名称
private String name;
//商品分类名称
private String catalog_name;
//价格
private double price;
//商品描述
private String description;
//图片名称
private String picture;
}
创建ResultModel类
public class ResultModel {
private List
//商品总数
private Long recordCount;
//总页数
private int pageCount;
//当前页
private int currentPage;
}
Dao
功能
接收service层传递过来的参数,根据参数查询索引库,返回查询结果。
创建ProductDao接口,定义一个查询方法
public interface ProductDao {
//查询商品信息,包括分页信息
public ResultModel queryProduct(SolrQuery query) throws Exception;
}
创建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 product = null;
//高亮信息
Map
.getHighlighting();
for (SolrDocument solrDocument : documentList) {
product = new Product();
product.setPid((String) solrDocument.get("id"));
String prodName = (String) solrDocument.get("product_name");
List
"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;
}
}
Service
功能分析
接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。
接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
创建ProductService接口,定义一个查询方法
public interface ProductService {
public ResultModel queryProduct(String queryString, String cataName,
String price, String sort, Integer curPage) throws Exception;
}
创建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("");
query.setHighlightSimplePost("");
ResultModel result = productDao.queryProduct(query);
result.setCurrentPage(curPage);
//总页数 = 总数量 / 每页数据条数 结果向上取整
double ceil = Math.ceil(result.getRecordCount().doubleValue()/20);
result.setPageCount((int)ceil);
return result;
}
}
Controller
创建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";
}
}
测试搜索功能
地址:http://localhost:8080/solr-demo-02-jd/list.action