热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java项目中用到的solr_Solr的原理及在项目中的使用实例.

前面已经讲过如果安装及配置Solr服务器了,那么现在我们就来正式在代码中使用Solr.1,这里Solr主要是怎么使用的呢?当我们在前台页面搜索商品名称关键词时,我们这时是在Solr

前面已经讲过 如果安装及配置Solr服务器了, 那么现在我们就来正式在代码中使用Solr.

1,这里Solr主要是怎么使用的呢?

当我们在前台页面搜索商品名称关键词时, 我们这时是在Solr库中去查找相应的商品信息, 然后将搜索关键词高亮.

2,那么Solr库中的商品信息又是如何添加的呢?

当我们在给商品上架的时候, 将商品信息update 到mysql数据库中的bbs_product表中, 然后同样的将相应的信息 添加到Solr库中.

接下来就看代码的具体实现吧:

一, 商品上架

811ea8ec3501ecc917098435b812b01d.png

我们在这里点击上架按钮:

list.jsp:1 

点击上架触发isShow事件:

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

接着到Controller层:

ProductController.java:1 //添加页面2     @RequestMapping("/isShow.do")3     public String isShow(Long[] ids, Model model){4         productService.isShow(ids);5         return "forward:/product/list.do";6     }

接着看Service层:

ProdcutServiceImpl.java:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 //上架@Autowired

private SolrServer solrServer; 2     public void isShow(Long[] ids){ 3         Product product = new Product(); 4         product.setIsShow(true); 5         for (Long id : ids) { 6             //上下架状态 7             product.setId(id); 8             productDao.updateByPrimaryKeySelective(product); 9             10             //TODO 保存商品信息到Solr服务器11             SolrInputDocument doc = new SolrInputDocument();12             //ID13             doc.setField("id", id);14             //名称15             Product p = productDao.selectByPrimaryKey(id);16             doc.setField("name_ik", p.getName());17             //图片URL18             doc.setField("url", p.getImgUrls()[0]);19             //品牌 ID20             doc.setField("brandId", p.getBrandId());21             //价格 sql查询语句: select price from bbs_sku where product_id = ? order by price asc limit 122             SkuQuery skuQuery = new SkuQuery();23             skuQuery.createCriteria().andProductIdEqualTo(id);24             skuQuery.setOrderByClause("price asc");25             skuQuery.setPageNo(1);26             skuQuery.setPageSize(1);27             List skus = skuDao.selectByExample(skuQuery);28             doc.setField("price", skus.get(0).getPrice());29             //...时间等 剩下的省略30             31             try {32                 solrServer.add(doc);33                 solrServer.commit();34             } catch (Exception e) {35                 // TODO Auto-generated catch block36                 e.printStackTrace();37             }38             //TODO 静态化39         }40     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

这里使用SolrInputDocument 来保存商品信息, 其中doc.setField("name_ik", p.getName());的name_ik 是我们在solr 配置文件配置的IK 分词器的字段, doc.setField("url", p.getImgUrls()[0]); 这里我们也只是取第一张图片的url用来展示.

这里我们还用到了skuQuery, 因为一个商品中不同的颜色不同的尺码都可能有不同的价格, 我们在这里 是取到同一个productId下价格最小的来给显示~

然后再就是将我们已经设置好的SolrInputDocument通过SolrServer 来提交到Solr服务器. SolrServer是已经在spring中注册好了的, 在这里直接注入即可使用.

spring来管理Solr:

bbc810348826cbccd2b3b7bbc0c0b69e.png

到了这里上架的功能就做好了, 这也是给后面Solr查询做好铺垫.

二, 前台使用Solr查询到了这里就开始查看前台页面了, 前台页面是扒的网上的, 具体业务逻辑是自己修改的, 页面如下:

25bf52c89f85ffdf2e0405d6107a46d3.png

这里需要特殊说明一下, 我们配置的全局拦截器变成了: / , 而且过滤掉静态资源, 配置如下:

首先是babasport-portal project下的web.xml文件:

8f900a89c6347c561fdf2122f13be562.png View Code

第二个就是babasport-portal project下的spring配置文件中设置过滤掉静态资源:1 2     3     4     

这样就就可以直接访问了.

当我们输入2016 点击查询后会出现什么? 我把已经做好的页面展示一下:

9baa2a34b146237c00ef7239b4978916.png

那么就进入到实际的开发当中:

当我们在搜索框输入2016 且点击 搜索时:

5da0f84dd06759d7f2cf0a0d9fd1e3c5.png

然后到Controller层去找到search方法:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private SearchService searchService; 3      4     //去首页 5     @RequestMapping(value="/") 6     public String index(){ 7         return "index"; 8     } 9     10     //搜索11     @RequestMapping(value="/search")12     public String search(Integer pageNo, String keyword, String price, Long brandId,  Model model){13         //品牌结果集  Redis中14         List brands = searchService.selectBrandListFromRedis();15         model.addAttribute("brands", brands);16         17         //map 装已经选择的条件18         Map map = new HashMap();19         if(null != brandId){20             for (Brand brand : brands) {21                 if(brandId.equals(brand.getId())){22                     map.put("品牌", brand.getName());23                     break;24                 }25             }26         }27         //价格 0-99 1600以上28         if(null != price){29             String[] split = price.split("-");30             //如果切割后的长度等于2 就说明这是一个价格区间31             if(split.length == 2){32                 map.put("价格", price);33             }else {34                 map.put("价格", price + "以上");35             }36         }37         model.addAttribute("map", map);38         39         Pagination pagination = searchService.selectPaginationFromSolr(pageNo, keyword, price, brandId);40         model.addAttribute("pagination", pagination);41         model.addAttribute("keyword", keyword);42         model.addAttribute("price", price);43         model.addAttribute("brandId", brandId);44         45         return "search";46     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

提示: 这里使用到了SolrService, 相信看我以前博文的朋友都知道这个地方还需要配置dubbo, 就是服务提供方和适用方, 这里为了简便直接略过, 实际开发中是必须要配置的, 否则就调用不了SolrService中的方法了.

这个controller 中往search.jsp中put了很多东西, 具体这些东西什么用我们可以先不管, 我们先看下search.jsp页面.

而且这个controller中查询brand 是从redis中查询出来的, 我们会在下面讲到这个.

48304ba5e6f9fe08f3fa1abda7d326ab.png1  2             

3                 已选条件: 4                      5                         6                             ${m.key }:${m.value } 7                          8                      9             
10             

48304ba5e6f9fe08f3fa1abda7d326ab.png

上面这个地方就是为何要在controller设置map值了, 这个是显示已选择的过滤条件.

48304ba5e6f9fe08f3fa1abda7d326ab.png1  2 

3     
4         
品牌:
 5         
6             
7                 
  •  8                  9                     
  • 10                         ${brand.name }11                     12                 13                 
14             
15         
16     
17 
18 19 20 
21     
22         
价格:
23         
24             
25                 
  • 26                     
  • 27                         0-9928                     29                     
  • 30                         100-29931                     32                     
  • 33                         300-59934                     35                     
  • 36                         600-99937                     38                     
  • 39                         1000-159940                     41                     
  • 42                         1600以上43                     44                 
45             
46         
47     
48 
49 

48304ba5e6f9fe08f3fa1abda7d326ab.png

接下来我们来看下对应的js方法:

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

这个就可以实现 添加 过滤条件的选项了.

三, 使用Redis 取出商品品牌列表

首先 当我们在后台添加或者修改品牌时, 我们应该同样将这个品牌添加到Redis中, 格式类似于: {"brandId":"brandName"}

controller层:(当我们在后台添加或者修改品牌)

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private Jedis jedis; 3     //修改 4     public void updateBrandById(Brand brand){ 5         //保存或修改 时修改Redis中的品牌, hmset适合批量添加品牌 6         /*Map map = new HashMap(); 7         map.put(String.valueOf(brand.getId()), brand.getName()); 8         jedis.hmset("brand", map);*/ 9         jedis.hset("brand", String.valueOf(brand.getId()), brand.getName());10         brandDao.updateBrandById(brand);11     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

redis中有了品牌列表后, 然后就是查询了:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private Jedis jedis; 3     //查询Redis中的品牌结果集 4     public List selectBrandListFromRedis(){ 5         List brands = new ArrayList(); 6         Map hgetAll = jedis.hgetAll("brand"); 7         Set> entrySet = hgetAll.entrySet(); 8         for (Entry entry : entrySet) { 9             Brand brand = new Brand();10             brand.setId(Long.parseLong(entry.getKey()));11             brand.setName(entry.getValue());12             brands.add(brand);13         }14         15         return brands;16     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

到了这里redis查询brand就完成了, 那么继续看下关于solr 是如何加入过滤条件的吧:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired  2     private SolrServer solrServer;  3     //查询商品信息从Solr  4     public Pagination selectPaginationFromSolr(Integer pageNo, String keyword, String price, Long brandId){  5         ProductQuery productQuery = new ProductQuery();  6         //当前页  7         productQuery.setPageNo(Pagination.cpn(pageNo));  8         //每页数  9         productQuery.setPageSize(8); 10          11         SolrQuery solrQuery = new SolrQuery(); 12         //关键词 商品名称 13         solrQuery.set("q", "name_ik:"+keyword); 14         //回显数据 15         StringBuilder params = new StringBuilder(); 16         params.append("keyword=").append(keyword); 17          18         //排序 19         solrQuery.addSort("price", ORDER.asc); 20          21         //高亮 22         //1,设置, 打开高亮的开关 23         solrQuery.setHighlight(true); 24         //2, 设置高亮字段 25         solrQuery.addHighlightField("name_ik"); 26         //3, 设置关键字高亮的样式 2016 27         //设置前缀和后缀 28         solrQuery.setHighlightSimplePre(""); 29         solrQuery.setHighlightSimplePost(""); 30          31         //过滤条件 品牌 32         if(null != brandId){ 33             solrQuery.addFilterQuery("brandId:"+brandId); 34             params.append("&brandId=").append(brandId); 35         } 36         //过滤价格 0-99  1600 37         if(null != price){ 38             String[] split = price.split("-"); 39             //如果切割后的长度等于2 就说明这是一个价格区间 40             if(split.length == 2){ 41                 solrQuery.addFilterQuery("price:["+split[0]+" TO "+split[1]+"]"); 42             }else { 43                 solrQuery.addFilterQuery("price:["+split[0]+" TO *]"); 44             } 45             params.append("&price=").append(price); 46         } 47          48         //分页  limit 开始行,每页数 49         solrQuery.setStart(productQuery.getStartRow()); 50         solrQuery.setRows(productQuery.getPageSize()); 51          52         QueryResponse response = null; 53         try { 54             response = solrServer.query(solrQuery); 55              56         } catch (Exception e) { 57             e.printStackTrace(); 58         } 59         //分析这个Map 60         //第一层Map: Key String == ID : Value: Map 61         //第二层Map: Key String == name_ik : Value: List 62         //获取到List: String 0,1,2.... 63         Map>> highlighting = response.getHighlighting(); 64          65          66         List products = new ArrayList(); 67         //结果集 68         SolrDocumentList docs = response.getResults(); 69         //总条数 70         long numFound = docs.getNumFound(); 71         for (SolrDocument doc : docs) { 72             Product product = new Product(); 73             //商品的ID 74             String id = (String)doc.get("id"); 75             product.setId(Long.parseLong(id)); 76              77             //取第二层Map 78             Map> map = highlighting.get(id); 79             //取List集合 80             List list = map.get("name_ik"); 81              82             //商品名称 83             //String name = (String)doc.get("name_ik"); 84             //product.setName(name); 85             product.setName(list.get(0)); //list.get(0) 中的name是已经设置为高亮的 86              87             //图片 88             String url = (String)doc.get("url"); 89             product.setImgUrl(url); 90             //价格 这里的价格本身是保存在bbs_sku表中的, 而我们在这里将price属性直接添加到了Product中 91             //因为我们在做上架的时候, 查询的是bbs_sku中price最小的值 然后保存到solr中的, 所以这里我们就直接将price属性添加到product中了 92             //这里的价格只有一个值 93             //Float price = (Float)doc.get("price"); 94             product.setPrice((Float)doc.get("price")); 95             //品牌ID 96             //Integer brandId = (Integer)doc.get("brandId"); 97             product.setBrandId(Long.parseLong(String.valueOf((Integer)doc.get("brandId")))); 98             products.add(product); 99         }100         101         Pagination pagination = new Pagination(102                     productQuery.getPageNo(),103                     productQuery.getPageSize(),104                     (int)numFound,105                     products106                 );107         //页面展示108         String url = "/search";109         pagination.pageView(url, params.toString());110         111         return pagination;112     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

这个就是本博文的重中之重了, code上面都加了注释, 相信还是比较容易理解的.

5f37628559badc978b16f0236e792138.png



推荐阅读
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
author-avatar
mobiledu2502856963
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有