什么是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";
}
}