solr_架構案例【京東站內搜索】(附程序源代碼)

注意事項:首先要保證部署solr服務的Tomcat容器和檢索solr服務中數據的Tomcat容器,它們的端口號不能發生衝突,不然web程序是不可能運行起來的。前端

一:solr服務的端口號、我這裏的solr服務的tomcat容器的端口號已經修改成8083:java

 

二:檢索solr服務中數據的tomcat容器的端口號、我這裏是8080:
web

 

 

最後必需要保證2個容器能正常訪問。spring

 

 

需求使用Solr實現電商網站中商品信息搜索功能,能夠根據關鍵字搜索商品信息,根據商品分類、價格過濾搜索結果,也能夠根據價格進行排序,實現分頁。apache

界面以下:spring-mvc

一、架構分析:tomcat

本身開發的應用:架構

Controller層的做用:獲取搜索條件,並響應搜索結果到前臺頁面。mvc

Service層的做用:接收Controller傳遞過來的參數,根據參數拼裝一個查詢條件,調用dao層方法,查詢商品數據;接收返回的商品列表和商品的總數量,根據每頁顯示的商品數量計算總頁數。app

Dao層的做用:接收Service層傳遞過來的參數,根據參數去檢索solr索引庫中的商品數據,返回查詢結果。

 

二、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>

 

三、各個開發層的代碼實現,程序中基本附帶註釋:

【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         //一、查詢並獲取響應結果:
32         QueryResponse response = solrServer.query(solrQuery);
33         
34         //二、從響應中獲取結果集:
35         SolrDocumentList results = response.getResults();
36         
37         //三、處理結果集:
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         //一、封裝查詢條件對象,由於須要調用dao層的方法,dao層的檢索方法就須要一個solr服務的查詢條件對象:
32         SolrQuery solrQuery = new SolrQuery();
33         
34         //二、設置默認查詢的域(該默認的域已經在solrHome/collection1/conf/schema.xml配置文件中配置了業務域):
35         solrQuery.setQuery("product_keywords");
36         
37         //三、設置查詢的關鍵字:
38         if(queryString!=null && !"".equals(queryString)){
39             solrQuery.setQuery(queryString);
40         }else{
41             //若是沒有查詢的關鍵字,則默認查詢全部商品數據:
42             solrQuery.setQuery("*:*");
43         }
44         
45         //四、根據商品分類進行過濾:
46         if(catalog_name!=null && !"".equals(catalog_name)){
47             //注意查詢語法:不要忽略":"號
48             solrQuery.addFilterQuery("product_catalog_name:" + catalog_name);
49         }
50         
51         //五、根據商品價格進行過濾:
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         //六、按照商品價格排序展現商品數據:
62         if("1".equals(sort)){
63             solrQuery.setSort("product_price",ORDER.asc);
64         }else{
65             solrQuery.setSort("product_price",ORDER.desc);
66         }
67         
68         //七、分頁查詢商品數據:
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         //八、根據封裝後的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類的數據模型截個圖給你們分享一下(案例所需的基本程序都在這裏了,但願能幫到你們,若是有什麼不對的地方望各位指教!!!):

相關文章
相關標籤/搜索