什麼是Solr:
DocumentObjectBinder binder=new DocumentObjectBinder();
//binder.getBean(clazz, solrDoc)
3.3.2創建application-service.xml
什麼是Solr:
Solr是一個企業級數據檢索的服務器,是一個開源的javaee項目。
Http請求給檢索服務器提交數據(xml或者json字符串),檢索服務器可以把客戶端提交的數據進行整理。建立出一個目錄索引。
也可以根據客戶端的Get請求得到XML或者JSON字符串格式的返回數據
非結構化數據中提取出的然後重新組織的信息,我們稱之索引
這便是Solr使用與工作原理:
Solrj是什麼?
Solrj就是訪問Solr的API
1.1使用Solrj更新索引庫
/**
* 更新索引庫
*/
@Test
public void updateIndex() {
try {
//建立和solr服務的鏈接
HttpSolrServer server=new
HttpSolrServer("http://localhost:8080/solr/solrCore");
//創建SolrInputDocument對象
SolrInputDocument doc=new SolrInputDocument();
//給doc對象賦值,封裝數據
doc.addField("id",999999);
doc.addField("product_name", "雙11銷售女朋友,送男朋友");
doc.addField("product_catalog", 44);
doc.addField("product_catalog_name", "數碼");
doc.addField("product_price", 123456.00);
doc.addField("product_picture", "1.png");
doc.addField("product_description", "買一送一.....");
//將文檔對象添加索引庫
server.add(doc);
//提交http請求
server.commit();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
1.2 Solrj刪除索引庫
/****
* 刪除索引庫
*/
@Test
public void deleteIndex() {
try {
//建立和solr服務的鏈接
HttpSolrServer server=new
HttpSolrServer("http://localhost:8080/solr/solrCore");
//根據id刪除
server.deleteById("999999");
server.commit();
} catch (Exception e) {
// TODO: handle exception
}
}
1.3: 使用Solrj進行索引庫的查詢操作:
/***
* 索引庫查詢操作
*/
@Test
public void searchIndex() {
try {
//建立和solr服務的鏈接
HttpSolrServer server=new
HttpSolrServer("http://localhost:8080/solr/solrCore");
//創建SolrQuery對象
SolrQuery params=new SolrQuery();
//params對象中峯查詢參數
//封裝關鍵字查詢條件q查詢
//params.set("q", "product_name:花兒朵朵彩色金屬門後掛");
params.setQuery("花兒朵朵彩色金屬門後掛");
//封裝過濾查詢條件,按照商品的類型過濾
params.addFilterQuery("product_catalog_name:幽默雜貨");
//封裝過濾查詢條件,按照價格區間過濾
params.addFilterQuery("product_price:[10 TO 20]");
//封裝查詢結果排序參數
params.setSort("product_price",ORDER.desc);
//封裝分頁查詢參數
params.setStart(8);
params.setRows(4);
//字段投影(指定需要查詢的字段)
//params.setFields("id","product_name");
//指定默認查詢字段
params.set("df","product_name");
//打開高亮顯示效果
params.setHighlight(true);
//指定需要顯示的高亮字段
params.addHighlightField("product_name");
//指定高亮顯示的前綴和後綴
params.setHighlightSimplePre("<font color='red'>");
params.setHighlightSimplePost("</font>");
//查詢索引庫,返回響應結果
QueryResponse response=server.query(params);
//獲得查詢到的文檔對象集合
SolrDocumentList results=response.getResults();
//獲得高亮數據的集合
Map<String, Map<String, List<String>>>
htls = response.getHighlighting();
//獲得查詢到的商品總數
long total = results.getNumFound();
System.out.println("total="+total);
//遍歷文檔對象集合
for(SolrDocument doc:results) {
String id=String.valueOf(doc.get("id"));
System.out.println(id);
String product_name=String.valueOf(doc.get("product_name"));
//獲取某個商品對應的高亮數據
Map<String, List<String>> hls=htls.get(id);
//獲得某個商品中某個字段對應的高亮數據
List<String> lts=hls.get("product_name");
if(lts!=null && lts.size()>0) {
product_name=lts.get(0);
}
System.out.println(product_name);
System.out.println(doc.get("product_catalog"));
System.out.println(doc.get("product_catalog_name"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_picture"));
//System.out.println(doc.get("product_description"));
System.out.println("==================================");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
2.4: Solrj實現查詢結果的封裝
封裝所需要的實體類:
package com.bjsxt.pojo;
import org.apache.solr.client.solrj.beans.Field;
/***
* 商品的實體類
* @author EDZ
*
*/
public class Product {
@Field
private String id;
@Field
private String product_name;
@Field
private Integer product_catalog;
@Field
private String product_catalog_name;
@Field
private Double product_price;
@Field
private String product_picture;
@Field
private String product_description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public Integer getProduct_catalog() {
return product_catalog;
}
public void setProduct_catalog(Integer product_catalog) {
this.product_catalog = product_catalog;
}
public String getProduct_catalog_name() {
return product_catalog_name;
}
public void setProduct_catalog_name(String product_catalog_name) {
this.product_catalog_name = product_catalog_name;
}
public Double getProduct_price() {
return product_price;
}
public void setProduct_price(Double product_price) {
this.product_price = product_price;
}
public String getProduct_picture() {
return product_picture;
}
public void setProduct_picture(String product_picture) {
this.product_picture = product_picture;
}
public String getProduct_description() {
return product_description;
}
public void setProduct_description(String product_description) {
this.product_description = product_description;
}
}
查詢結果的封裝(
DocumentObjectBinder binder=new DocumentObjectBinder();
//binder.getBean(clazz, solrDoc)
)
/****
* 實現查詢結果的封裝
*/
@Test
public void searchIndex2() {
try {
//建立和solr服務的鏈接
HttpSolrServer server=new
HttpSolrServer("http://localhost:8080/solr/solrCore");
//創建SolrQuery對象
SolrQuery params=new SolrQuery();
//params對象中峯查詢參數
//封裝關鍵字查詢條件q查詢
//params.set("q", "product_name:花兒朵朵彩色金屬門後掛");
params.setQuery("花兒朵朵彩色金屬門後掛");
params.set("df", "product_name");
//打開高亮顯示效果
params.setHighlight(true);
//指定需要顯示的高亮字段
params.addHighlightField("product_name");
//指定高亮顯示的前綴和後綴
params.setHighlightSimplePre("<font color='red'>");
params.setHighlightSimplePost("</font>");
//查詢索引庫,返回響應結果
QueryResponse response=server.query(params);
//獲得高亮數據的集合
Map<String, Map<String, List<String>>>
htls = response.getHighlighting();
//獲得查詢到的文檔對象集合
SolrDocumentList results=response.getResults();
//創建DocumentObjectBinder對象,實現文檔對象綁定
DocumentObjectBinder binder=new DocumentObjectBinder();
//binder.getBean(clazz, solrDoc)
//將文檔對象集合轉化爲實體類對象的集合
List<Product> list = binder.getBeans(Product.class, results);
for(Product p:list) {
String id = p.getId();
//獲得某個商品對應的高亮數據
Map<String, List<String>> hts = htls.get(id);
//獲得某個商品的某個字段的高亮數據
List<String> lts = hts.get("product_name");
if(lts!=null&<s.size()>0) {
p.setProduct_name(lts.get(0));
}
//System.out.println(p.getId());
System.out.println(p.getProduct_name());
/*System.out.println(p.getProduct_catalog_name());
System.out.println(p.getProduct_price());
System.out.println(p.getProduct_picture());*/
}
//list集合中商品對象的name屬性是否包含高亮數據
//return list;
//將文檔對象的集合results轉化爲Product對象的集合
/*for(SolrDocument doc:results) {
//1
//2
//3
}*/
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
2.5 Solrj 實現索引庫的更新優化:
/***
* 索引庫更新優化
*/
@Test
public void updateIndex2() {
try {
//select * from product where dataupdate between 當前系統日期-24 and 當前系統日期
//查詢數據庫的操作(jdbc,mybatis)
//數據庫查詢到的數據是實體類對象的集合
List<Product> list=new ArrayList<Product>();
Product p1=new Product();
p1.setId("999999");
p1.setProduct_name("java高手葵花寶典");
p1.setProduct_description("高手訓練手冊....");
p1.setProduct_price(1234.00);
p1.setProduct_picture("1.png");
Product p2=new Product();
p2.setId("777777");
p2.setProduct_name("java高手葵花寶典 java高手葵花寶典");
p2.setProduct_description("高手訓練手冊....java高手葵花寶典");
p2.setProduct_price(1234.00);
p2.setProduct_picture("1.png");
list.add(p1);
list.add(p2);
//建立和solr服務的鏈接
HttpSolrServer server=new
HttpSolrServer("http://localhost:8080/solr/solrCore");
for(Product p:list) {
server.addBean(p);
//提交http請求
server.commit();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
實戰:Solr 項目JD
3.1創建JD項目(war)
3.2添加項目依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt.jd</groupId>
<artifactId>jd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 添加javaee的依賴 -->
<dependencies>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- jsp -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<!--
provided該jar在項目運行階段由tomcat容器提供
項目打包的時候,不能將該jar打到項目中
-->
<scope>provided</scope>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- solr的api依賴 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>4.10.4</version>
</dependency>
<!-- 日誌的commonlogging.jar -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 添加tomcat插件 -->
<plugin>
<artifactId>tomcat7-maven-plugin</artifactId>
<groupId>org.apache.tomcat.maven</groupId>
<version>2.2</version>
<configuration>
<!-- 配置tomcat容器的端口號 -->
<port>8081</port>
<!-- 配置項目的上下文 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.3配置Spring
3.3.1創建application-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 實例化HttpSolrServer對象 -->
<bean id="server" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<!-- 構造注入,調用帶參數構造方法 -->
<constructor-arg name="baseURL"
value="http://localhost:8080/solr/solrCore"></constructor-arg>
</bean>
<!-- 掃描dao對象 -->
<context:component-scan base-package="com.bjsxt.dao.impl"></context:component-scan>
</beans>
3.3.2創建application-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 掃描業務對象 -->
<context:component-scan base-package="com.bjsxt.service.impl"></context:component-scan>
</beans>
3.3.3創建springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 掃描Controller對象 -->
<context:component-scan base-package="com.bjsxt.controller"></context:component-scan>
<!-- springmvc註解驅動 -->
<mvc:annotation-driven></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>
<!-- 靜態資源方行 -->
<mvc:resources location="/images/" mapping="/images/**"></mvc:resources>
<mvc:resources location="/resource/" mapping="/resource/**"></mvc:resources>
</beans>
3.4配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>jd</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 加載spring容器(spring的xml文件) -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-*.xml</param-value>
</context-param>
<!-- 註冊監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置前端控制器,servlet -->
<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>/</url-pattern>
</servlet-mapping>
<!-- 配置過濾器,處理post請求的亂碼 -->
<filter>
<filter-name>charset</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>charset</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.5功能實現
3.5.1創建Product實體類
package com.bjsxt.pojo;
import org.apache.solr.client.solrj.beans.Field;
/***
* 商品的實體類
* @author EDZ
*
*/
public class Product {
@Field
private String id;
@Field
private String product_name;
@Field
private Integer product_catalog;
@Field
private String product_catalog_name;
@Field
private Double product_price;
@Field
private String product_picture;
@Field
private String product_description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public Integer getProduct_catalog() {
return product_catalog;
}
public void setProduct_catalog(Integer product_catalog) {
this.product_catalog = product_catalog;
}
public String getProduct_catalog_name() {
return product_catalog_name;
}
public void setProduct_catalog_name(String product_catalog_name) {
this.product_catalog_name = product_catalog_name;
}
public Double getProduct_price() {
return product_price;
}
public void setProduct_price(Double product_price) {
this.product_price = product_price;
}
public String getProduct_picture() {
return product_picture;
}
public void setProduct_picture(String product_picture) {
this.product_picture = product_picture;
}
public String getProduct_description() {
return product_description;
}
public void setProduct_description(String product_description) {
this.product_description = product_description;
}
}
3.5.2創建ProductDao接口
package com.bjsxt.dao;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
public interface ProductDao {
/***
* 實現商品數據的檢索
*/
public QueryResponse loadProductDao(SolrQuery params);
}
3.5.3創建ProductDaoImpl實現類
package com.bjsxt.dao.impl;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.bjsxt.dao.ProductDao;
@Repository
public class ProductDaoImpl implements ProductDao {
//注入HttpSolrServer對象
@Autowired
private HttpSolrServer server;
@Override
public QueryResponse loadProductDao(SolrQuery params) {
// TODO Auto-generated method stub
try {
return server.query(params);
} catch (SolrServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
3.5.4創建ProductService接口
package com.bjsxt.service;
import java.util.Map;
import com.bjsxt.pojo.ProductVo;
public interface ProductService {
/***
* 實現商品信息檢索
*/
public Map<String,Object> loadProductListService(ProductVo pvo,
Integer page,Integer rows);
}
3.5.5創建ProductServiceImpl實現類
package com.bjsxt.service.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.bjsxt.dao.ProductDao;
import com.bjsxt.pojo.Product;
import com.bjsxt.pojo.ProductVo;
import com.bjsxt.service.ProductService;
@Service
public class ProductServiceImpl implements ProductService {
//注入dao對象
@Autowired
private ProductDao productDao;
@Override
public Map<String, Object> loadProductListService(ProductVo pvo,
Integer page,Integer rows) {
// TODO Auto-generated method stub
//創建SolrQuery對象
SolrQuery params=new SolrQuery();
//獲得查詢的關鍵字,實現關鍵字查詢
String product_name=pvo.getProduct_name();
if(!StringUtils.isEmpty(product_name)) {
params.set("df", "product_name");
params.setQuery(product_name);
}else {
//查詢所有商品信息
params.set("q", "*:*");
}
//商品類目過濾查詢
String product_catalog_name=pvo.getProduct_catalog_name();
if(!StringUtils.isEmpty(product_catalog_name)) {
params.addFilterQuery("product_catalog_name:"+product_catalog_name);
}
//商品的價格區間過濾器查詢
Double min=pvo.getMin();
Double max=pvo.getMax();
if(min!=null) {
if(max.equals(-1.0)) {
max=Double.MAX_VALUE;
}
params.addFilterQuery("product_price:["+min+" TO "+max+"]");
}
/***
* 價格排序
*/
Integer sort=pvo.getSort();
if(sort.equals(0)) {
params.setSort("product_price", ORDER.asc);
}else {
params.setSort("product_price", ORDER.desc);
}
/***
* 指定分頁查詢參數
*/
Integer start=(page-1)*rows;
params.setStart(start);
params.setRows(rows);
/****
* 打開高亮顯示
*/
params.setHighlight(true);
params.addHighlightField("product_name");
params.setHighlightSimplePre("<font color='red'>");
params.setHighlightSimplePost("</font>");
//查詢索引庫
QueryResponse response = productDao.loadProductDao(params);
//獲得高亮顯示的數據
Map<String, Map<String, List<String>>> htls = response.getHighlighting();
//獲得查詢到的文檔對象的集合
SolrDocumentList results = response.getResults();
//將results集合,轉化Product對象的集合
DocumentObjectBinder binder=new DocumentObjectBinder();
List<Product> beans = binder.getBeans(Product.class, results);
//遍歷beans集合
for(Product p:beans) {
/***
* 處理高亮數據
*/
String id=p.getId();
Map<String, List<String>> lts = htls.get(id);
//獲得某個商品特徵字段對應的高亮數據
List<String> lst = lts.get("product_name");
if(lst!=null&&lst.size()>0) {
p.setProduct_name(lst.get(0));
}
}
//查詢到的商品總數
long total = results.getNumFound();
//計算獲得最大頁
long mpage=total%rows==0?total/rows:(total/rows)+1;
//將文檔對象results轉化爲
Map<String, Object> map=new HashMap<String, Object>();
map.put("results", beans);
map.put("total", total);
map.put("mpage", mpage);
return map;
}
}
3.5.6創建ProductController
package com.bjsxt.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.bjsxt.pojo.ProductVo;
import com.bjsxt.service.ProductService;
@Controller
public class ProductController {
@Autowired
private ProductService productService;
/***
* 實現頁面跳轉
*/
@RequestMapping("/")
public String loadPage() {
return "index";
}
/***
* 處理商品檢索的請求
*/
@RequestMapping("/loadProduct")
public String loadProduct(ProductVo pvo,
@RequestParam(defaultValue="1")Integer page,
@RequestParam(defaultValue="16")Integer rows,
Model model) {
Map<String, Object> result
= productService.loadProductListService(pvo, page, rows);
//作用用戶封裝數據
model.addAttribute("list", result.get("results"));
model.addAttribute("total", result.get("total"));
model.addAttribute("mpage", result.get("mpage"));
model.addAttribute("page", page);
model.addAttribute("vo", pvo);
return "index";
}
}