[项目构建 七]babasport 商品上架及Solr使用实例.
Posted 一枝花算不算浪漫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[项目构建 七]babasport 商品上架及Solr使用实例.相关的知识,希望对你有一定的参考价值。
前面已经讲过 如果安装及配置Solr服务器了, 那么现在我们就来正式在代码中使用Solr.
1,这里Solr主要是怎么使用的呢?
当我们在前台页面搜索商品名称关键词时, 我们这时是在Solr库中去查找相应的商品信息, 然后将搜索关键词高亮.
2,那么Solr库中的商品信息又是如何添加的呢?
当我们在给商品上架的时候, 将商品信息update 到mysql数据库中的bbs_product表中, 然后同样的将相应的信息 添加到Solr库中.
接下来就看代码的具体实现吧:
一, 商品上架
我们在这里点击上架按钮:
list.jsp:
1 <div style="margin-top:15px;"><input class="del-button" type="button" value="删除" onclick="optDelete();"/><input class="add" type="button" value="上架" onclick="isShow(\'${name}\', \'${brandId }\', \'${isShow }\' ,\'${pagination.pageNo }\')"/><input class="del-button" type="button" value="下架" onclick="isHide();"/></div>
点击上架触发isShow事件:
1 <script type="text/javascript"> 2 //上架 3 function isShow(name,brandId,isShow,pageNo){ 4 //请至少选择一个 5 var size = $("input[name=\'ids\']:checked").size(); 6 if(size == 0){ 7 alert("请至少选择一个"); 8 return; 9 } 10 //你确定上架吗 11 if(!confirm("你确定上架吗")){ 12 return; 13 } 14 //提交 Form表单 15 $("#jvForm").attr("action","/product/isShow.do?name="+ name +"&brandId="+brandId+"&isShow="+isShow+"&pageNo="+pageNo); 16 $("#jvForm").attr("method","post"); 17 $("#jvForm").submit(); 18 19 } 20 </script>
接着到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 //ID 13 doc.setField("id", id); 14 //名称 15 Product p = productDao.selectByPrimaryKey(id); 16 doc.setField("name_ik", p.getName()); 17 //图片URL 18 doc.setField("url", p.getImgUrls()[0]); 19 //品牌 ID 20 doc.setField("brandId", p.getBrandId()); 21 //价格 sql查询语句: select price from bbs_sku where product_id = ? order by price asc limit 1 22 SkuQuery skuQuery = new SkuQuery(); 23 skuQuery.createCriteria().andProductIdEqualTo(id); 24 skuQuery.setOrderByClause("price asc"); 25 skuQuery.setPageNo(1); 26 skuQuery.setPageSize(1); 27 List<Sku> 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 block 36 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文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 5 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 6 7 <!-- Post过滤器 --> 8 <filter> 9 <filter-name>encoding</filter-name> 10 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 11 <init-param> 12 <param-name>encoding</param-name> 13 <param-value>UTF-8</param-value> 14 </init-param> 15 </filter> 16 17 <filter-mapping> 18 <filter-name>encoding</filter-name> 19 <url-pattern>/</url-pattern> 20 </filter-mapping> 21 22 <!-- 前端控制器 --> 23 <servlet> 24 <servlet-name>portal</servlet-name> 25 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 26 <init-param> 27 <param-name>contextConfigLocation</param-name> 28 <!-- 默认读取的是 WEB-INF/console-servlet.xml --> 29 <param-value>classpath:springmvc-portal.xml</param-value> 30 </init-param> 31 <load-on-startup>1</load-on-startup> 32 </servlet> 33 34 <servlet-mapping> 35 <servlet-name>portal</servlet-name> 36 <!-- 37 /*: 拦截视图请求: .jsp .js .css 几乎不用,配置静态资源过滤 38 /: 拦截所有,不拦截.jsp 文件, 但是同样拦截.js .css 如果使用也需要配置静态资源过滤(前台系统使用) 39 *.do:拦截所有以.do请求, 后台开发应用*.do 40 --> 41 <url-pattern>/</url-pattern> 42 </servlet-mapping> 43 </web-app>
第二个就是babasport-portal project下的spring配置文件中设置过滤掉静态资源:
1 <!-- 过滤静态资源 --> 2 <mvc:resources location="/js/" mapping="/js/*.*"/> 3 <mvc:resources location="/css/" mapping="/css/*.*"/> 4 <mvc:resources location="/images/" mapping="/images/*.*"/>
这样就就可以直接访问了.
当我们输入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<Brand> brands = searchService.selectBrandListFromRedis(); 15 model.addAttribute("brands", brands); 16 17 //map 装已经选择的条件 18 Map<String, String> map = new HashMap<String, String>(); 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 <c:if test="${fn:length(map) != 0 }"> 2 <div class="sl-b-selected J_brandSelected"> 3 <span class="crumbs-arrow">已选条件:</span> 4 <c:forEach items="${map }" var="m"> 5 <a title="依琦莲(yiqilian)" href="javascript:;" class="crumb-select-item"> 6 <b>${m.key }:</b><em>${m.value }</em><i></i> 7 </a> 8 </c:forEach> 9 </div> 10 </c:if>
上面这个地方就是为何要在controller设置map值了, 这个是显示已选择的过滤条件.
1 <c:if test="${empty brandId }"> 2 <div class="J_selectorLine s-brand"> 3 <div class="sl-wrap"> 4 <div class="sl-key"><strong>品牌:</strong></div> 5 <div class="sl-value"> 6 <div class="sl-v-list"> 7 <ul class="J_valueList v-fixed"> 8 <c:forEach items="${brands }" var="brand"> 9 <li id="brand-38118" data-initial="j" style="display:block;"> 10 <a href="javascript:;" onclick="fqBrand(\'${brand.id }\')" title="${brand.name }"><i></i>${brand.name }</a> 11 </li> 12 </c:forEach> 13 </ul> 14 </div> 15 </div> 16 </div> 17 </div> 18 </c:if> 19 <c:if test="${empty price }"> 20 <div id="J_selectorPrice" class="J_selectorLine s-line"> 21 <div class="sl-wrap"> 22 <div class="sl-key"><span>价格:</span></div> 23 <div class="sl-value"> 24 <div class="sl-v-list"> 25 <ul class="J_valueList"> 26 <li> 27 <a href="javascript:;" onclick="fqPrice(\'0-99\')"><i></i>0-99</a> 28 </li> 29 <li> 30 <a href="javascript:;" onclick="fqPrice(\'100-299\')"><i></i>100-299</a> 31 </li> 32 <li> 33 <a href="javascript:;" onclick="fqPrice(\'300-599\')"><i></i>300-599</a> 34 </li> 35 <li> 36 <a href="javascript:;" onclick="fqPrice(\'600-999\')"><i></i>600-999</a> 37 </li> 38 <li> 39 <a href="javascript:;" onclick="fqPrice(\'1000-1599\')"><i></i>1000-1599</a> 40 </li> 41 <li> 42 <a href="javascript:;" onclick="fqPrice(\'1600\')"><i></i>1600以上</a> 43 </li> 44 </ul> 45 </div> 46 </div> 47 </div> 48 </div> 49 </c:if>
接下来我们来看下对应的js方法:
1 <script type="text/javascript"> 2 var price = \'${price}\'; 3 var brandId = \'${brandId}\'; 4 //过滤品牌id 5 function fqBrand(id){ 6 if(\'\' != price){ 7 window.location.href="/search?keyword="+ ${keyword} + "&brandId="+ id+"&price="+price; 8 }else{ 9 window.location.href="/search?keyword="+ ${keyword} + "&brandId="+ id; 10 } 11 } 12 13 //过滤价格 14 function fqPrice(id){ 15 if(\'\' != brandId){ 16 window.location.href = "/search?keyword=${keyword}" + "&brandId=" + brandId + "&price=" + id; 17 }else{ 18 window.location.href = "/search?keyword=${keyword}" + "&price=" + id; 19 } 20 } 21 </script>
这个就可以实现 添加 过滤条件的选项了.
三, 使用Redis 取出商品品牌列表
首先 当我们在后台添加或者修改品牌时, 我们应该同样将这个品牌添加到Redis中, 格式类似于: {"brandId":"brandName"}
controller层:(当我们在后台添加或者修改品牌)
1 @Autowired 2 private Jedis jedis; 3 //修改 4 public void updateBrandById(Brand brand){ 5 //保存或修改 时修改Redis中的品牌, hmset适合批量添加品牌 6 /*Map<String, String> map = new HashMap<String,String>(); 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<Brand> selectBrandListFromRedis(){ 5 List<Brand> brands = new ArrayList<Brand>(); 6 Map<String, String> hgetAll = jedis.hgetAll("brand"); 7 Set<Entry<String, String>> entrySet = hgetAll.entrySet(); 8 for (Entry<String, String> entry : entrySet) { 9 Brand brand = [项目构建 十五]babasport 项目总结及源码分享.[项目构建 八]babasport ActiveMQ的介绍及使用实例.
[项目构建 十四]babasport Mycat配置及使用详解.