前面已经讲过 如果安装及配置Solr服务器了, 那么现在我们就来正式在代码中使用Solr.
1,这里Solr主要是怎么使用的呢?
当我们在前台页面搜索商品名称关键词时, 我们这时是在Solr库中去查找相应的商品信息, 然后将搜索关键词高亮.
2,那么Solr库中的商品信息又是如何添加的呢?
当我们在给商品上架的时候, 将商品信息update 到mysql数据库中的bbs_product表中, 然后同样的将相应的信息 添加到Solr库中.
接下来就看代码的具体实现吧:
一, 商品上架
我们在这里点击上架按钮:
list.jsp:1
点击上架触发isShow事件:
1
接着到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:
1 //上架@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 }
这里使用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:
到了这里上架的功能就做好了, 这也是给后面Solr查询做好铺垫.
二, 前台使用Solr查询到了这里就开始查看前台页面了, 前台页面是扒的网上的, 具体业务逻辑是自己修改的, 页面如下:
这里需要特殊说明一下, 我们配置的全局拦截器变成了: / , 而且过滤掉静态资源, 配置如下:
首先是babasport-portal project下的web.xml文件:
View Code
第二个就是babasport-portal project下的spring配置文件中设置过滤掉静态资源:1 2 3 4
这样就就可以直接访问了.
当我们输入2016 点击查询后会出现什么? 我把已经做好的页面展示一下:
那么就进入到实际的开发当中:
当我们在搜索框输入2016 且点击 搜索时:
然后到Controller层去找到search方法:
1 @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 }
提示: 这里使用到了SolrService, 相信看我以前博文的朋友都知道这个地方还需要配置dubbo, 就是服务提供方和适用方, 这里为了简便直接略过, 实际开发中是必须要配置的, 否则就调用不了SolrService中的方法了.
这个controller 中往search.jsp中put了很多东西, 具体这些东西什么用我们可以先不管, 我们先看下search.jsp页面.
而且这个controller中查询brand 是从redis中查询出来的, 我们会在下面讲到这个.
1 2
上面这个地方就是为何要在controller设置map值了, 这个是显示已选择的过滤条件.
1 2
- 8 9
- 10 ${brand.name }11 12 13
- 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
接下来我们来看下对应的js方法:
1
这个就可以实现 添加 过滤条件的选项了.
三, 使用Redis 取出商品品牌列表
首先 当我们在后台添加或者修改品牌时, 我们应该同样将这个品牌添加到Redis中, 格式类似于: {"brandId":"brandName"}
controller层:(当我们在后台添加或者修改品牌)
1 @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 }
redis中有了品牌列表后, 然后就是查询了:
1 @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 }
到了这里redis查询brand就完成了, 那么继续看下关于solr 是如何加入过滤条件的吧:
1 @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 }
这个就是本博文的重中之重了, code上面都加了注释, 相信还是比较容易理解的.