注意事项:首先要保证部署solr服务的Tomcat容器和检索solr服务中数据的Tomcat容器,它们的端口号不能发生冲突,否则web程序是不可能运行起来的。
一:solr服务的端口号、我这里的solr服务的tomcat容器的端口号已经修改为8083:
二:检索solr服务中数据的tomcat容器的端口号、我这里是8080:
最后必须要保证2个容器能正常访问。
需求:使用Solr实现电商网站中商品信息搜索功能,可以根据关键字搜索商品信息,根据商品分类、价格过滤搜索结果,也可以根据价格进行排序,实现分页。
界面如下:
1、架构分析:
自己开发的应用:
Controller层的作用:获取搜索条件,并响应搜索结果到前台页面。
Service层的作用:接收Controller传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品数据;接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
Dao层的作用:接收Service层传递过来的参数,根据参数去检索solr索引库中的商品数据,返回查询结果。
2、WEB工程的搭建(相关的jar必须得全部引入,环境搭建篇中已经注明了):
需要说明的几点问题:
(a)、在springmvc核心配置文件中配置solr服务时,一定将solr服务的连接地址配置正确,否则无法找到solr索引库:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置注解扫描-->
<context:component-scan base-package="com.jd"/>
<!-- 配置注解驱动: 就相当于自动替我们配置注解形式的处理器映射器和处理器适配器 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置solrServer服务,供数据访问层检索数据使用: -->
<bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<!-- 配置构造方法 -->
<constructor-arg value="http://localhost:8083/solr/collection1"/>
</bean>
</beans>
(b)、在项目的web.xml配置文件中配置springmvc的前端控制器、post请求的乱码解决等问题:
<!-- 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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3、各个开发层的代码实现,程序中基本附带注释:
【Dao层】
1 package com.jd.dao;
2
3 import org.apache.solr.client.solrj.SolrQuery;
4
5 import com.jd.pojo.ResultModel;
6
7 /**
8 * 商品模块Dao接口:
9 * @author zxz
10 *
11 */
12
13 public interface ProductDao {
14
15 /**
16 * 根据检索条件检索solr服务上索引库中的数据:
17 * @param solrQuery
18 * @return
19 * @throws Exception
20 */
21 public ResultModel search(SolrQuery solrQuery) throws Exception;
22
23 }
1 package com.jd.dao;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import org.apache.solr.client.solrj.SolrQuery;
6 import org.apache.solr.client.solrj.SolrServer;
7 import org.apache.solr.client.solrj.response.QueryResponse;
8 import org.apache.solr.common.SolrDocument;
9 import org.apache.solr.common.SolrDocumentList;
10 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.stereotype.Repository;
12 import com.jd.pojo.ProductModel;
13 import com.jd.pojo.ResultModel;
14
15 /**
16 * 商品模块Dao层开发:
17 * 核心功能:接收Service层传递过来的参数,根据参数去检索solr索引库中的商品数据,返回查询结果
18 * @author zxz
19 *
20 */
21 @Repository
22 public class ProductDaoImpl implements ProductDao {
23
24 //注入solr服务(该solr服务在springmvc的核心配置文件中已经进行配置了):
25 @Autowired
26 private SolrServer solrServer;
27
28 //检索solr服务上索引库中的数据:
29 @Override
30 public ResultModel search(SolrQuery solrQuery) throws Exception {
31 //1、查询并获取响应结果:
32 QueryResponse response = solrServer.query(solrQuery);
33
34 //2、从响应中获取结果集:
35 SolrDocumentList results = response.getResults();
36
37 //3、处理结果集:
38 //专门用于存放响应结果集中的个个商品数据的集合
39 List<ProductModel> productList = new ArrayList<ProductModel>();
40 //用于将检索到的并处理好的数据封装到ResultModel对象中,用于返回给Service层:
41 ResultModel resultModel = new ResultModel();
42 //做非空校验,如果检索到的结果集不为空的话,就进行处理并封装结果数据:
43 if(results != null){
44 //(1)、封装查询到的商品总数:
45 resultModel.setRecordCount(results.getNumFound());
46
47 //(2)、遍历响应中的结果集,并将数据一一封装进ProductModel对象中:
48 for (SolrDocument document : results) {
49 //创建ProductModel对象:
50 ProductModel product = new ProductModel();
51 //商品id:
52 product.setPid(String.valueOf(document.get("id")));
53 //商品名称:
54 product.setName(String.valueOf(document.get("product_name")));
55 //商品价格:
56 if(String.valueOf(document.get("product_price"))!=null &&
57 !"".equals(String.valueOf(document.get("product_price")))){
58 product.setPrice(Float.valueOf(String.valueOf(document.get("product_price"))));
59 }
60 //商品图片:
61 product.setPicture(String.valueOf(document.get("product_picture")));
62
63 //将当前遍历并封装好的ProductModel对象添加到存放商品数据的集合中:
64 productList.add(product);
65 }
66
67 //循环处理并封装好结果集之后,将存放商品数据的集合设置到ResultModel对象中:
68 resultModel.setProductList(productList);
69 }
70
71 //将封装好的数据返回给Service层处理:
72 return resultModel;
73 }
74 }
【Service层】
1 package com.jd.service;
2
3 import com.jd.pojo.ResultModel;
4
5 /**
6 * 商品模块Service层接口:
7 * @author zxz
8 *
9 */
10
11 public interface ProductService {
12
13 /**
14 * 根据各种检索条件去调用dao层的方法,得到符合检索条件的数据:
15 * @param queryString
16 * @param catalog_name
17 * @param price
18 * @param page
19 * @param sort
20 * @return
21 * @throws Exception
22 */
23 public ResultModel search(String queryString, String catalog_name,
24 String price, Integer page, String sort) throws Exception;
25
26 }
1 package com.jd.service;
2
3 import org.apache.solr.client.solrj.SolrQuery;
4 import org.apache.solr.client.solrj.SolrQuery.ORDER;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Service;
7 import com.jd.dao.ProductDao;
8 import com.jd.pojo.ResultModel;
9
10 /**
11 * 商品模块Service层开发:
12 * 核心功能:接收Controller传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品数据。
13 * 接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。
14 * @author zxz
15 *
16 */
17 @Service
18 public class ProductServiceImpl implements ProductService {
19
20 //注入Dao:
21 @Autowired
22 private ProductDao productDao;
23
24 //定义常量,代表每页显示的商品条数:
25 private final static Integer PAGE_SIZE = 60;
26
27 //根据检索条件得到数据:
28 @Override
29 public ResultModel search(String queryString, String catalog_name, String price, Integer page, String sort)
30 throws Exception {
31 //1、封装查询条件对象,因为需要调用dao层的方法,dao层的检索方法就需要一个solr服务的查询条件对象:
32 SolrQuery solrQuery = new SolrQuery();
33
34 //2、设置默认查询的域(该默认的域已经在solrHome/collection1/conf/schema.xml配置文件中配置了业务域):
35 solrQuery.setQuery("product_keywords");
36
37 //3、设置查询的关键字:
38 if(queryString!=null && !"".equals(queryString)){
39 solrQuery.setQuery(queryString);
40 }else{
41 //如果没有查询的关键字,则默认查询所有商品数据:
42 solrQuery.setQuery("*:*");
43 }
44
45 //4、根据商品分类进行过滤:
46 if(catalog_name!=null && !"".equals(catalog_name)){
47 //注意查询语法:不要忽略":"号
48 solrQuery.addFilterQuery("product_catalog_name:" + catalog_name);
49 }
50
51 //5、根据商品价格进行过滤:
52 if(price!=null && !"".equals(price)){
53 //因为传递过来的的商品价格的格式为:100-300,所以需要切割并根据价格区间过滤商品数据:
54 String[] split = price.split("-");
55 if(split!=null && split.length>1){
56 //为什么判断长度必须大于1,因为根据价格过滤需要最小值和最大值,必须有俩个值才能过滤成功
57 solrQuery.addFilterQuery("product_price:["+split[0]+" TO "+split[1]+"]");
58 }
59 }
60
61 //6、按照商品价格排序展示商品数据:
62 if("1".equals(sort)){
63 solrQuery.setSort("product_price",ORDER.asc);
64 }else{
65 solrQuery.setSort("product_price",ORDER.desc);
66 }
67
68 //7、分页查询商品数据:
69 //首先校验数据合法性,如果当前页的值为空或小于1,则默认开始查询第一页数据:
70 if(page == null){
71 page = 1;
72 }
73 if(page < 1){
74 page = 1;
75 }
76 //计算起始索引:
77 Integer startIndex = (page-1) * PAGE_SIZE;
78 //设置起始索引:
79 solrQuery.setStart(startIndex);
80 //设置每页显示的商品记录数:
81 solrQuery.setRows(PAGE_SIZE);
82
83 //8、根据封装后的SolrQuery查询对象查询商品数据:
84 ResultModel resultModel = productDao.search(solrQuery);
85 //设置当前页数:
86 resultModel.setCurPage(page);
87 //计算总页数:
88 Long pageCount = (long) Math.ceil((resultModel.getRecordCount()*1.0) / PAGE_SIZE);
89 //设置总页数:
90 resultModel.setPageCount(pageCount);
91
92 return resultModel;
93 }
94 }
【Controller层】
1 package com.jd.controller;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.stereotype.Controller;
5 import org.springframework.ui.Model;
6 import org.springframework.web.bind.annotation.RequestMapping;
7 import com.jd.pojo.ResultModel;
8 import com.jd.service.ProductService;
9
10 /**
11 * 商品模块:
12 * @author zxz
13 *
14 */
15
16 @Controller
17 public class ProductController {
18
19 //注入Service接口:
20 @Autowired
21 private ProductService productService;
22
23 @RequestMapping("/list")
24 //根据条件和分页信息检索商品数据:
25 public String proList(String queryString, String catalog_name,
26 String price, Integer page, String sort,Model model) throws Exception{
27
28 //调用service层的方法得到检索后的数据:
29 ResultModel resultModel = productService.search(queryString, catalog_name, price, page, sort);
30
31 //将检索得到的数据返回给页面:
32 model.addAttribute("result", resultModel); //注意:这里的名称必须和jsp页面上获取数据的名称保持一致
33
34 //回显查询条件:
35 model.addAttribute("queryString", queryString); //这里的条件回显时,名称也必须和jsp页面上获取数据的名称保持一致
36 model.addAttribute("catalog_name", catalog_name);
37 model.addAttribute("price", price);
38 model.addAttribute("sort", sort);
39
40 return "product_list";
41 }
42 }
最后pojo类的数据模型截个图给大家分享一下(案例所需的基本程序都在这里了,希望能帮到大家,如果有什么不对的地方望各位指教!!!):