1..Solr案例實(shí)戰(zhàn)
1.1.需求
使用Solr實(shí)現(xiàn)電商網(wǎng)站中商品信息搜索功能,可以根據(jù)關(guān)鍵字、分類、價(jià)格搜索商品信息,也可以根據(jù)價(jià)格進(jìn)行排序,并且實(shí)現(xiàn)分頁功能。
界面如下:
1.2.分析
開發(fā)人員需要的文檔:靜態(tài)頁面(根據(jù)UI設(shè)計(jì)由美工給出)、數(shù)據(jù)庫設(shè)計(jì)、原型設(shè)計(jì)
1.2.1.UI分析
1.2.2.架構(gòu)分析

架構(gòu)分為:
(1)、solr服務(wù)器。(已經(jīng)做完,同入門示例)
(2)、自己開發(fā)的應(yīng)用(重點(diǎn))
(3)、數(shù)據(jù)庫mysql
自己開發(fā)的應(yīng)用
Controller 負(fù)責(zé)和前端頁面進(jìn)行請(qǐng)求和響應(yīng)的交互
Service 封裝查詢條件,調(diào)用dao。
Dao 搜索索引庫,返回搜索結(jié)果。
1.3.環(huán)境準(zhǔn)備
Solr:4.10.3
Jdk環(huán)境:1.7.0_72(solr4.10 不能使用jdk1.7以下)
Ide環(huán)境:Eclipse
Web服務(wù)器(servlet容器):Tomcat 7X
1.4.功能開發(fā)
1.4.1.第一步:創(chuàng)建web工程,導(dǎo)入jar包

--導(dǎo)入的jar包說明:
Solrj的包
Solr服務(wù)的日志包
Spring的包(包含springmvc)
核心包 4個(gè) core 、bean、context、expresstion
注解包 aop
Web包 web、webmvc
Commons日志包 common-logging
Jstl包
--導(dǎo)入靜態(tài)資源和jsp頁面說明:
靜態(tài)資源放在webapp目錄下,jsp頁面放到/WEB-INF/目錄下
1.4.2.第二步:Spring整合Solr、Springmvc
1.4.2.1.創(chuàng)建springmvc.xml
在config包下,創(chuàng)建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" />
<!-- 配置注解驅(qū)動(dòng) -->
<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.創(chuàng)建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.第三步:整合測(cè)試
1.4.3.1.需求:
訪問搜索頁面。
1.4.3.2.創(chuàng)建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.注意事項(xiàng)
(1)Solr服務(wù)器要先開啟。
(2)Solr服務(wù)器部署的Tomcat和本web應(yīng)用的部署的Tomcat不是同一個(gè)。
(3)要同時(shí)啟動(dòng)兩個(gè)Tomcat,要注意端口沖突問題。
6.修改Solr服務(wù)器的Tomcat的端口
--在server.xml文件中,修改端口
--tomcat端口說明:
8005:關(guān)機(jī)端口
8080:默認(rèn)服務(wù)端口
8009:請(qǐng)求轉(zhuǎn)向端口。
--注意:這三個(gè)端口都需要修改。不然啟動(dòng)會(huì)沖突
本次課程中,將solr的tomcat端口,修改為8888.
1.4.3.5.修改Springmvc.xml
--修改Solr服務(wù)的端口
<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

整合成功?。?!
1.4.4.第四步:搜索功能實(shí)現(xiàn)
分析代碼結(jié)構(gòu):
請(qǐng)求路徑=list.action
請(qǐng)求方式=POST
請(qǐng)求參數(shù)=queryString、catalog_name、price、curPage、sort(共5個(gè))
返回結(jié)果=定義Product 以及ProductModel
1.4.4.1.Pojo
1.4.4.1.1.分析
結(jié)合查詢界面,分析得出:
--需要一個(gè)商品的pojo(Product),存放商品信息
--需要一個(gè)包裝pojo(ResultModel),它包括商品列表信息、商品分頁信息
1.4.4.1.2.創(chuàng)建Product類
public class Product {
// 商品編號(hào)
private String pid;
// 商品名稱
private String name;
// 商品分類名稱
private String catalog_name;
// 價(jià)格
private double price;
// 商品描述
private String description;
// 圖片名稱
private String picture;
}
1.4.4.1.3.創(chuàng)建ResultModel類
public class ResultModel {
private List<Product> productList;
// 商品總數(shù)
private Long recordCount;
// 總頁數(shù)
private int pageCount;
// 當(dāng)前頁
private int currentPage;
}
1.4.4.2.Dao
1.4.4.2.1.功能
接收service層傳遞過來的參數(shù),根據(jù)參數(shù)查詢索引庫,返回查詢結(jié)果。
1.4.4.2.2.創(chuàng)建ProductDao接口,定義一個(gè)查詢方法
public interface ProductDao {
//查詢商品信息,包括分頁信息
public ResultModel queryProduct(SolrQuery query) throws Exception;
}
1.4.4.2.3.創(chuàng)建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);
// 獲得查詢結(jié)果
SolrDocumentList documentList = response.getResults();
// 把查詢結(jié)果總數(shù)設(shè)置到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傳遞過來的參數(shù),根據(jù)參數(shù)拼裝一個(gè)查詢條件,調(diào)用dao層方法,查詢商品列表??
接收返回的商品列表和商品的總數(shù)量,根據(jù)每頁顯示的商品數(shù)量計(jì)算總頁數(shù)。
1.4.4.3.2.創(chuàng)建ProductService接口,定義一個(gè)查詢方法
public interface ProductService {
public ResultModel queryProduct(String queryString, String cataName,
String price, String sort, Integer curPage) throws Exception;
}
1.4.4.3.3.創(chuàng)建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);
}
//判斷商品價(jià)格是否為空
if(!"".equals(price) && null != price){
String[] prices = price.split("-");
if(prices.length == 2){
query.addFilterQuery("product_price:["+prices[0]+" TO "+prices[1]+"]");
}
}
//設(shè)置排序
if("1".equals(sort)){
query.setSort("product_price", ORDER.desc);
}else {
query.setSort("product_price", ORDER.asc);
}
//設(shè)置分頁信息
if(null == curPage){
curPage = 1;
}
query.setStart((curPage-1)*20);
query.setRows(20); //每頁20條數(shù)據(jù)
//設(shè)置默認(rèn)搜索域
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);
// 總頁數(shù) = 總數(shù)量 / 每頁數(shù)據(jù)條數(shù) 結(jié)果向上取整
double ceil = Math.ceil(result.getRecordCount().doubleValue()/20);
result.setPageCount((int)ceil);
return result;
}
}
1.4.4.4.Controller
1.4.4.4.1.創(chuàng)建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";
}
}
1.4.4.5.測(cè)試搜索功能
地址:http://localhost:8080/solr-demo-02-jd/list.action
