1..Solr案例实战
1.1.需求
使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能。
界面如下:
1.2.分析
开发人员需要的文档:静态页面(根据UI设计由美工给出)、数据库设计、原型设计
1.2.1.UI分析
1.2.2.架构分析
image.png架构分为:
(1)、solr服务器。(已经做完,同入门示例)
(2)、自己开发的应用(重点)
(3)、数据库mysql
自己开发的应用
Controller 负责和前端页面进行请求和响应的交互
Service 封装查询条件,调用dao。
Dao 搜索索引库,返回搜索结果。
1.3.环境准备
Solr:4.10.3
Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下)
Ide环境:Eclipse
Web服务器(servlet容器):Tomcat 7X
1.4.功能开发
1.4.1.第一步:创建web工程,导入jar包
image.png--导入的jar包说明:
Solrj的包
Solr服务的日志包
Spring的包(包含springmvc)
核心包 4个 core 、bean、context、expresstion
注解包 aop
Web包 web、webmvc
Commons日志包 common-logging
Jstl包
--导入静态资源和jsp页面说明:
静态资源放在webapp目录下,jsp页面放到/WEB-INF/目录下
1.4.2.第二步:Spring整合Solr、Springmvc
1.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>
1.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>
1.4.3.第三步:整合测试
1.4.3.1.需求:
访问搜索页面。
1.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;
}
}
1.4.3.4.注意事项
(1)Solr服务器要先开启。
(2)Solr服务器部署的Tomcat和本web应用的部署的Tomcat不是同一个。
(3)要同时启动两个Tomcat,要注意端口冲突问题。
6.修改Solr服务器的Tomcat的端口
--在server.xml文件中,修改端口
--tomcat端口说明:
8005:关机端口
8080:默认服务端口
8009:请求转向端口。
--注意:这三个端口都需要修改。不然启动会冲突
本次课程中,将solr的tomcat端口,修改为8888.
1.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>
1.4.3.6.访问搜索页面
地址:http://localhost:8080/solr-demo-02-jd/product_list.action
image.png整合成功!!!
1.4.4.第四步:搜索功能实现
分析代码结构:
请求路径=list.action
请求方式=POST
请求参数=queryString、catalog_name、price、curPage、sort(共5个)
返回结果=定义Product 以及ProductModel
1.4.4.1.Pojo
1.4.4.1.1.分析
结合查询界面,分析得出:
--需要一个商品的pojo(Product),存放商品信息
--需要一个包装pojo(ResultModel),它包括商品列表信息、商品分页信息
1.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;
}
1.4.4.1.3.创建ResultModel类
public class ResultModel {
private List<Product> productList;
// 商品总数
private Long recordCount;
// 总页数
private int pageCount;
// 当前页
private int currentPage;
}
1.4.4.2.Dao
1.4.4.2.1.功能
接收service层传递过来的参数,根据参数查询索引库,返回查询结果。
1.4.4.2.2.创建ProductDao接口,定义一个查询方法
public interface ProductDao {
//查询商品信息,包括分页信息
public ResultModel queryProduct(SolrQuery query) throws Exception;
}
1.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;
}
}
1.4.4.3.Service
1.4.4.3.1.功能分析
接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表??
接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
1.4.4.3.2.创建ProductService接口,定义一个查询方法
public interface ProductService {
public ResultModel queryProduct(String queryString, String cataName,
String price, String sort, Integer curPage) throws Exception;
}
1.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;
}
}
1.4.4.4.Controller
1.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";
}
}
网友评论