精华内容
下载资源
问答
  •  完成关键字搜索功能  能够实现高亮显示效果  完成查询分类列表的功能  完成条件过滤构建功能  完成分页动态页码展示 一、完成关键字搜索 1.首先构建工程 pinyougou_search_interface pinyougou_search_...

    今日目标:

        完成关键字搜索功能
        能够实现高亮显示效果
        完成查询分类列表的功能
        完成条件过滤构建功能
        完成分页动态页码展示

    一、完成关键字搜索

    1.首先构建工程    pinyougou_search_interface    pinyougou_search_service    pinyougou_search_web

    参考content的工程,因为也不需要安全框架

    2.关键字的需求分析

    我们分析输入关键字,可以通过商品或者商家或者title等四个参数进行所有

    参数的分析:首先我们的返回的参数可能是itemList   规格  品牌   分类   价格区间    当前页   每页显示的条数,两种方法,一种是自己封装一个类,把这些参数封装起来,还有一种是通过Map实现,因为考虑到还要维护这个类,所以我们采用map的方式进行封装

    后端代码实现:

    service层的代码实现过程
    /**
     * 搜索功能的实现类
     */
    @Service
    @Transactional
    public class SearchServiceImpl implements SearchService {
    
        @Autowired
        private SolrTemplate solrTemplate;//注意添加solr的配置文件
        @Override
        public Map<String, Object> search(Map searchMap) {
            //创建高亮显示对象
            HighlightQuery query = new SimpleHighlightQuery();//接口我们通过其子类实现即可
     // 一.  1.关键字搜索
            String keywords = (String) searchMap.get("keywords");
            Criteria criteria = null;
            //2.判断关键字是否为空
            if (keywords!=null&&!"".equals(keywords)){
                //不等于空
                //输入关键字条件条件
                criteria = new Criteria("item_keywords").is(keywords);
            }else{
                //关键字为空,查询所有 通过一个表达式  *:*
                criteria = new Criteria().expression("*:*");
            }
    
            //3.将查询的条件添加到criteria中
            query.addCriteria(criteria);
            //4.这个条件已经封装了,query需要查询的所有条件
            HighlightPage<TbItem> page = solrTemplate.queryForHighlightPage(query, TbItem.class);
            //当前页的信息
            List<TbItem>  content = page.getContent();
            Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("rows",content);
            return resultMap;
        }
    }
    
    接口方法;
    /**
     * 搜索接口的方法
     */
    public interface SearchService {
        //商品的搜索参数   通过map格式,Object是不同的类型,包括品牌,规格,分类 价格区间 每页显示条数 每页记录数
        public Map<String,Object> search(Map searchMap);
    }

    controller层的实现

    @RestController
    @RequestMapping("search")
    public class SearchController {
    
        @Reference
        private SearchService searchService;
    
        /**
         * 搜索功能那的实现
         * @param searchMap
         * @return
         */
        @RequestMapping("searchMap")
        Map <String,Object> search(@RequestBody Map searchMap){
          return  searchService.search(searchMap);
        }
    }
    

    前台代码的实现:

    controller层

    app.controller("searchController",function ($scope,$controller,searchService) {
    
        //控制器继承代码
        $controller("baseController",{$scope:$scope});
    
        //构建封装搜索条件的对象
        $scope.searchMap={
          keywords:"",
            category:"",
            brand:"",
            spec:{},//规格属性,需要规格名称和规格选项
            price:"",
            sort:"ASC",
            sortField:"",
            pageNo:1,//当前页
            pageSize:60//每页记录数
        };
        //商品搜索
        $scope.search=function () {
            searchService.search($scope.searchMap).success(function (response) {
                $scope.resultMap=response;
                //构建分页工具条
                //
            })
        }
        
    })

    service:

    //服务层
    app.service('searchService',function($http){
    
        //搜索功能的实现
        this.search=function(searchMap){
            return $http.post('itemsearch/search.do',searchMap);
        }
    });
    

    注意:一定要把方法里面的参数写对

    二.实现搜索高亮显示

    思路分析:我们通过在一个搜索关键字上添加前缀和后缀,以此来显示关键字的高亮,我们把业务模块都写在service层

    我们通过分析,在返回值的resultMap中的title没有设置高亮的样式,那么我们继续往上面找,如上图所示,我们通过遍历highlighted来获取,注意判断里面的list集合是否为空,得到值后直接进行赋值操作

    后端代码实现:

    //当前页的信息
            List<TbItem>  content = page.getContent();
            for (TbItem item : content) {
                //处理高亮结果
                List<HighlightEntry.Highlight> highlights = page.getHighlights(item);
                //判断highlightsshif为空
                if (highlights!=null&& highlights.size()>0){
                    //获取高亮结果集
                    List<String> snipplets = highlights.get(0).getSnipplets();
                    //在判断是否为空
                    if (snipplets!=null&& snipplets.size()>0){
                        item.setTitle(snipplets.get(0));
                    }
                }
            }

    注意出现这个问题,html代码直接没有被解析而是直接显示在页面上,这是angularjs出于安全考虑,防止hmtl注入,我们将设置权限

    我们写一个filter的过滤器

    定义过滤器,处理字符串为HTML标签
    //使用方式:<em ng-bind-html="带标签的数据 | trustHtml"></em>
    app.filter("trustHtml",function($sce){
    	return function(data){
    		return $sce.trustAsHtml(data);
    	};
    });

    页面处理:

    通过angularjs的一个指令实现:

    <em ng-bind-html="entity.title | trustHtml"></em>

    效果如图:

    三.过滤添加条件

    思路分析:在这我们只涉及一些写死的数据提交,也可以通过查询实现,分类,品牌,以及规格的显示,通过模板关联品牌和规格,注意:规格我们需要提交精确的其值,那么我们需要判断要对那个条件进行封装

    1.组合查询条件的实现  

    前端代码实现:

     //组合条件的查询
        $scope.addFilterCondition=function (key,value) {
            if (key=="category" || key=="price" || key=="brand"){
                $scope.searchMap[key]=value;
            }else{
                $scope.searchMap.spec[key]=value;
            }
    
            //调用查询方法
            $scope.search();
        }

    后台实现:

     //3.将查询的条件添加到criteria中
            query.addCriteria(criteria);
            //三.1.构建分类的查询条件
            String category = (String) searchMap.get("category");
            //2.判断查询条件是否为空
            if (category!=null&&!"".equals(category)){
                //构建分类查询条件
                Criteria categoryCriteria = new Criteria("item_category").is(category);
                //构建过滤条件查询
                FilterQuery filterQuery = new SimpleFilterQuery(categoryCriteria);
                //将查询的条件添加到query 中
                query.addFilterQuery(filterQuery);
            }
            //四.构建品牌查询条件
            String brand = (String)searchMap.get("brand");
            //判断是否为空
            if (brand!=null&&!"".equals(brand)){
                //构建品牌查询提哦案件
                Criteria brandCriteria = new Criteria("item_brand").is(brand);
                //构建过滤条件查询
                FilterQuery filterQuery  = new SimpleFilterQuery(brandCriteria);
                //将查询的条件添加到总的query 中
                query.addFilterQuery(filterQuery);
            }

    2.规格的功能的实现,由于我们分装的是一个实体类 spec  所以我们也没有必要在创建一个实体类,我们通过Map格式封装

    后台代码实现:

    //五.  封装规格
            //获取spec的对象格式
            Map<String,String> specMap = (Map<String, String>) searchMap.get("spec");
            //判断map的结果是否Wie空
            if (specMap!=null){
                //通过遍历它的key值,获得value值,就是规格选项的值
                for (String key: specMap.keySet()){
                    //构建品牌查询提哦案件
                    Criteria specificationCriteria = new Criteria("item_spec_"+key).is(specMap.get(key));
                    //构建过滤条件查询
                    FilterQuery filterQuery  = new SimpleFilterQuery(specificationCriteria);
                    //将查询的条件添加到总的query 中
                    query.addFilterQuery(filterQuery);
                }
            }

    3.根据价格实现功能

    思路:我们要对字符串进行判断处理,splic("-")   然后通过这个第一个值  0 和最后一个值*  判断

     //六.价格的条件查询
            String price = (String)searchMap.get("price");
            //分析:
            /*
            ('price','0-500')
            ('price','500-1000')
            ('price','1000-1500')
            ('price','2000-3000')
              ('price','3000-*')分析可知通过分隔符分开,然后分割后成为一个数组,最后
              通过临界值判断
             */
            //判断是否为空
            if (price!=null&&!"".equals(price)){
                String[] split = price.split("-");
                //通过价格临界值判断
                if (!"0".equals(split[0])){
                    //构建查询条件  大于0这个区间
                    Criteria priceCriteria= new Criteria("item_price").greaterThanEqual(split[0]);
                    //构建过滤条件查询
                    FilterQuery filterQuery  = new SimpleFilterQuery(priceCriteria);
                    //将查询的条件添加到总的query 中
                    query.addFilterQuery(filterQuery);
                }
    
                //通过* 判断  小于等于1的这个区间
                if (!"*".equals(split[1])){
                    //构建查询条件
                    Criteria priceCriteria= new Criteria("item_price").lessThanEqual(split[1]);
                    //构建过滤条件查询
                    FilterQuery filterQuery  = new SimpleFilterQuery(priceCriteria);
                    //将查询的条件添加到总的query 中
                    query.addFilterQuery(filterQuery);
                }
            }

     

    四.排序功能实现

    需求:

    实现如下图:

    查询操作实现,新品和价格排序

     

     

     

     

    这个是上一个模块移除的内容,点击已经添加的条件,实现移除的功能

    思路:我们通过点击传过来的的key值,删除value注意还要判断是spec,因为这个是对象,我们通过这个delete   方法删除这个key以及value

    //移除查询条件操作  //通过key移除值
    $scope.removeSearchItem=function (key) {
    
        if (key=="category" || key=="price" || key=="brand"){
            $scope.searchMap[key]="";
        }else{
          delete  $scope.searchMap.spec[key];
        }
        //调用查询方法
        $scope.search();
    }

    五.搜索分页功能实现

    思想:通过传过来pageNo当前页,pageSize总页数,作为条件,后台做处理,然后返回给前台

     

    后台代码:

     //八.构建分页查询
            Integer pageNo = (Integer) searchMap.get("pageNo");
            Integer pageSize = (Integer) searchMap.get("pageSize");
            query.setOffset((pageNo-1)*pageSize);//设置分页起始值
            query.setRows(pageSize);//设置总页数
    //最后还的封装一下
     Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("rows",content);
            resultMap.put("totalpagee",page.getTotalPages());//总页数
            resultMap.put("pageNo",pageNo);//当前页
            return resultMap;

    前台代码实现:

       //构建分页工具条代码
        buildPageLabel=function(){
            $scope.pageLabel = [];// 新增分页栏属性,存放分页的页面
            var maxPageNo = $scope.resultMap.totalPages;// 得到最后页码
    
            // 定义属性,显示省略号
            $scope.firstDot = true;
            $scope.lastDot = true;
    
            var firstPage = 1;// 开始页码
            var lastPage = maxPageNo;// 截止页码
    
            if ($scope.resultMap.totalPages > 5) { // 如果总页数大于5页,显示部分页码
                if ($scope.resultMap.pageNo <= 3) {// 如果当前页小于等于3
                    lastPage = 5; // 前5页
                    // 前面没有省略号
                    $scope.firstDot = false;
    
                } else if ($scope.searchMap.pageNo >= lastPage - 2) {// 如果当前页大于等于最大页码-2
                    firstPage = maxPageNo - 4; // 后5页
                    // 后面没有省略号
                    $scope.lastDot = false;
                } else {// 显示当前页为中心的5页
                    firstPage = $scope.searchMap.pageNo - 2;
                    lastPage = $scope.searchMap.pageNo + 2;
                }
            } else {
                // 页码数小于5页  前后都没有省略号
                $scope.firstDot = false;
                $scope.lastDot = false;
            }
            // 循环产生页码标签
            for (var i = firstPage; i <= lastPage; i++) {
                $scope.pageLabel.push(i);
            }
        }
    
    
        //分页查询
        $scope.queryForPage=function(pageNo){
            $scope.searchMap.pageNo=pageNo;
    
            //执行查询操作
            $scope.search();
    
        }
    
        //分页页码显示逻辑分析:
        // 1,如果页面数不足5页,展示所有页号
        // 2,如果页码数大于5页
        // 1) 如果展示最前面的5页,后面必须有省略号.....
        // 2) 如果展示是后5页,前面必须有省略号
        // 3) 如果展示是中间5页,前后都有省略号
    
        // 定义函数,判断是否是第一页
        $scope.isTopPage = function() {
            if ($scope.searchMap.pageNo == 1) {
                return true;
            } else {
                return false;
            }
        }
        // 定义函数,判断是否最后一页
        $scope.isLastPage = function() {
            if ($scope.searchMap.pageNo == $scope.resultMap.totalPages) {
                return true;
            } else {
                return false;
            }
        }
    

    六.总结

     

    展开全文
  • 在开发电商项目时,我们需要实现一个最基本的功能:点击商品的图片,打开商品详情页面。其中,商品页面分为三大部分: a) 商品基本信息 b) 延迟加载商品详情。延迟一秒加载使用ajax c) 商品的规格参数。按需加载,当...

    概述

    在开发电商项目时,我们需要实现一个最基本的功能:点击商品的图片,打开商品详情页面。其中,商品页面分为三大部分:

    a) 商品基本信息

    b) 延迟加载商品详情。延迟一秒加载使用ajax

    c) 商品的规格参数。按需加载,当用户点击商品规格参数tab页,加载ajax。

    1.功能分析

    1、Taotao-portal接收页面请求,接收到商品id。

    2、调用taotao-rest提供的商品详情的服务,把商品id作为参数传递给服务。接收到商品详细详细。

    3、渲染结果,展示商品详细页面

    4、为了提高响应速度,商品详情页的内容需要分步骤加载。

    第一步:先展示商品基本信息,例如商品的名称、图片、价格。

    第二步:展示商品的描述,此时商品页面已经展示完毕,需要ajax请求商品描述。展示的时机是页面加载完毕后一秒钟。

    第三步:展示商品规格。当用户点击商品规格选项卡时展示。使用ajax请求商品规格。

    5、在搜索页面点击商品的图片或者商品名称请求商品详情页面。

    商品详情页请求的url:/item/{itemId}.html

    商品描述请求的url:/item/desc/{itemId}.html

    商品规格请求的url:/item/param/{itemId}.html

    2.处理流程

    img

    3.taotao-rest服务发布

    需要在taotao-rest工程中发布服务

    1、取商品基本信息的服务

    2、取商品描述的服务

    3、取商品规格的服务

    由于商品详情也是客户经常访问的,需要把商品信息添加到缓存中。Redis是内存数据库也属于稀缺资源,所以不应该永久占用,所以要设置过期时间。过期时间为一天。需要缓存同步。

    3.1添加缓存逻辑

    Redis的hash类型中的key是不能设置过期时间。如果还需要对key进行分类可以使用折中的方案。

    Key的命名方式:XXXX:xxxx:~~~~

    这样存放在redis中,当我们用可视化客户端时就会以文件夹形式存储

    img

    因此,在配置文件resource.properties添加url

    #商品基本信息url
    ITEM_INFO_URL=/item/info/
    #商品描述url
    ITEM_DESC_URL=/item/desc/
    #商品规格参数url
    ITEM_PARAM_URL=/item/param/
    

    3.2Dao层

    因为都是单表查询所以使用逆向工程生成的mapper文件即可。

    tb_item

    tb_item_desc

    tb_item_param_item

    3.3Service层

    @Service
    public class ItemServiceImpl implements ItemService {
    	@Autowired
    	private TbItemMapper itemMapper;
    	@Autowired
    	private TbItemDescMapper itemDescMapper;
    	@Autowired
    	private TbItemParamItemMapper itemParamItemMapper;
    	@Value("${REDIS_ITEM_KEY}")
    	private String REDIS_ITEM_KEY;
    	@Value("${REDIS_ITEM_EXPIRE}")
    	private Integer REDIS_ITEM_EXPIRE;
    	@Autowired
    	private JedisClientSingle jedisClientSingle;
    
    	@Override
    	public TaotaoResult getItemBaseInfo(long itemId) {
    		//添加缓存逻辑
    		try {
    			//从缓存中取商品信息,商品id对应的信息
    			String json = jedisClientSingle.get(REDIS_ITEM_KEY+":"+itemId+":base");
    			if(!StringUtils.isBlank(json)) {
    				//把json转换成java对象
    				TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
    				return TaotaoResult.ok(item);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		//根据商品id查询商品信息
    		TbItem item = itemMapper.selectByPrimaryKey(itemId);
    		//把商品信息写入缓存
    		try {
    			jedisClientSingle.set(REDIS_ITEM_KEY+":"+itemId+":base", JsonUtils.objectToJson(item));
    			//设置key的有效期
    			jedisClientSingle.expire(REDIS_ITEM_KEY+":"+itemId+":base", REDIS_ITEM_EXPIRE);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return TaotaoResult.ok(item);
    	}
    
    	@Override
    	public TaotaoResult getItemDesc(long itemId) {
    		//添加缓存
    		try {
    			//添加缓存逻辑
    			//从缓存中取商品信息,商品id对应的信息
    			String json = jedisClientSingle.get(REDIS_ITEM_KEY + ":" + itemId + ":desc");
    			//判断是否有值
    			if (!StringUtils.isBlank(json)) {
    				//把json转换成java对象
    				TbItemDesc itemDesc = JsonUtils.jsonToPojo(json, TbItemDesc.class);
    				return TaotaoResult.ok(itemDesc);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		//创建查询条件
    		TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
    		
    		try {
    			//把商品信息写入缓存
    			jedisClientSingle.set(REDIS_ITEM_KEY + ":" + itemId + ":desc", JsonUtils.objectToJson(itemDesc));
    			//设置key的有效期
    			jedisClientSingle.expire(REDIS_ITEM_KEY + ":" + itemId + ":desc", REDIS_ITEM_EXPIRE);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		return TaotaoResult.ok(itemDesc);
    	}
    
    	@Override
    	public TaotaoResult getItemParam(long itemId) {
    		//添加缓存
    		try {
    			//添加缓存逻辑
    			//从缓存中取商品信息,商品id对应的信息
    			String json = jedisClientSingle.get(REDIS_ITEM_KEY + ":" + itemId + ":param");
    			//判断是否有值
    			if (!StringUtils.isBlank(json)) {
    				//把json转换成java对象
    				TbItemParamItem paramItem = JsonUtils.jsonToPojo(json, TbItemParamItem.class);
    				return TaotaoResult.ok(paramItem);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		//根据商品id查询规格参数
    		//设置查询条件
    		TbItemParamItemExample example = new TbItemParamItemExample();
    		Criteria criteria = example.createCriteria();
    		criteria.andItemIdEqualTo(itemId);
    		//执行查询
    		List<TbItemParamItem> list = itemParamItemMapper.selectByExampleWithBLOBs(example);
    		if (list != null && list.size()>0) {
    			TbItemParamItem paramItem = list.get(0);
    			try {
    				//把商品信息写入缓存
    				jedisClientSingle.set(REDIS_ITEM_KEY + ":" + itemId + ":param", JsonUtils.objectToJson(paramItem));
    				//设置key的有效期
    				jedisClientSingle.expire(REDIS_ITEM_KEY + ":" + itemId + ":param", REDIS_ITEM_EXPIRE);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			return TaotaoResult.ok(paramItem);
    		}
    		return TaotaoResult.build(400, "无此商品规格");
    	}
    
    }
    

    3.4Controller层

    @Controller
    @RequestMapping("/item")
    public class ItemController {
    	@Autowired
    	private ItemService itemService;
    	
    	@RequestMapping("/info/{itemId}")
    	@ResponseBody
    	public TaotaoResult getItemBaseInfo(@PathVariable Long itemId) {
    		TaotaoResult result = itemService.getItemBaseInfo(itemId);
    		return result;
    	}
    	
    	@RequestMapping("/desc/{itemId}")
    	@ResponseBody
    	public TaotaoResult getItemDesc(@PathVariable Long itemId) {
    		TaotaoResult result = itemService.getItemDesc(itemId);
    		return result;
    	}
    
    	@RequestMapping("/param/{itemId}")
    	@ResponseBody
    	public TaotaoResult getItemParam(@PathVariable Long itemId) {
    		TaotaoResult result = itemService.getItemParam(itemId);
    		return result;
    	}
    
    }
    

    4.taotao-portal商品详情页实现

    4.1需求分析

    当用户访问商品详情页面时,需要加载商品基本信息。延迟加载商品描述、按需加载商品的规格参数。

    img

    由于页面展示商品信息时,需要展示图片列表。多张图片在数据库中存储的格式是存储在同一个字段中使用逗号分隔的。所以商品展示时需要在pojo中做处理。故此在portal中自定义一个商品的pojo类继承TbItem同时新增一个get方法。

    //添加此方法拆分图片列表
    public String[] getImages() {
        if (image != null && image != "") {
            String[] strings = image.split(",");
            return strings;
        }
        return null;
    }
    

    4.2Service层

    商品基本信息的查询:

    接收商品id调用mapper查询商品规格参数,返回规格参数pojo使用TaotaoResult包装。添加缓存逻辑。

    商品描述延迟加载:

    接收商品id,调用taotao-rest的服务,查询商品的基本信息。得到一个json字符串。需要把json转换成java对象。然后在jsp页面渲染。

    商品规格参数展示:

    接收商品id,调用taotao-rest的服务根据商品id查询商品描述信息。得到json数据。把json转换成java对象从java对象中把商品描述取出来。返回商品描述字符串。

    参数:商品id

    返回值:字符串(商品描述的html片段)

    /**
     * 商品内容展示Service
     * @author JY
     *
     */
    @Service
    public class ItemServiceImpl implements ItemService {
    	@Value("${ITEM_INFO_URL}")
    	private String ITEM_INFO_URL;
    	@Value("${REST_BASE_URL}")
    	private String REST_BASE_URL;
    	@Value("${ITEM_DESC_URL}")
    	private String ITEM_DESC_URL;
    	@Value("${ITEM_PARAM_URL}")
    	private String ITEM_PARAM_URL;
    
    	@Override
    	public ItemInfo getItemInfoById(long itemId) {
    		try {
    			//调用rest的服务查询商品基本信息
    			String json = HttpClientUtil.doGet(REST_BASE_URL+ITEM_INFO_URL+itemId);
    			if(!StringUtils.isBlank(json)) {
    				TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, ItemInfo.class);
    				if(taotaoResult.getStatus()==200) {
    					ItemInfo itemInfo = (ItemInfo) taotaoResult.getData();
    					return itemInfo;
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	//取商品描述
    	@Override
    	public String getItemDescById(Long itemId) {
    		try {
    			String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_DESC_URL + itemId);
    			//转换成java对象
    			TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItemDesc.class);
    			if (taotaoResult.getStatus() == 200) {
    				TbItemDesc itemDesc = (TbItemDesc) taotaoResult.getData();
    				//取商品描述信息
    				String result = itemDesc.getItemDesc();
    				return result;
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	//根据商品id查询规格参数
    	@Override
    	public String getItemParam(Long itemId) {
    		try {
    			String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_PARAM_URL + itemId);
    			//把json转换成java对象
    			TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItemParamItem.class);
    			if (taotaoResult.getStatus() == 200) {
    				TbItemParamItem itemParamItem = (TbItemParamItem) taotaoResult.getData();
    				String paramData = itemParamItem.getParamData();
    				//生成html
    				// 把规格参数json数据转换成java对象
    				List<Map> jsonList = JsonUtils.jsonToList(paramData, Map.class);
    				StringBuffer sb = new StringBuffer();
    				sb.append("<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"0\" class=\"Ptable\">\n");
    				sb.append("    <tbody>\n");
    				for(Map m1:jsonList) {
    					sb.append("        <tr>\n");
    					sb.append("            <th class=\"tdTitle\" colspan=\"2\">"+m1.get("group")+"</th>\n");
    					sb.append("        </tr>\n");
    					List<Map> list2 = (List<Map>) m1.get("params");
    					for(Map m2:list2) {
    						sb.append("        <tr>\n");
    						sb.append("            <td class=\"tdTitle\">"+m2.get("k")+"</td>\n");
    						sb.append("            <td>"+m2.get("v")+"</td>\n");
    						sb.append("        </tr>\n");
    					}
    				}
    				sb.append("    </tbody>\n");
    				sb.append("</table>");
    				//返回html片段
    				return sb.toString();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		return "";
    
    	}
    	
    }
    

    4.3Controller层

    /**
     * 商品内容展示
     * @author JY
     *
     */
    @Controller
    public class ItemController {
    	@Autowired
    	private ItemService itemService;
    	
    	@RequestMapping("/item/{itemId}")
    	public String showItem(@PathVariable Long itemId,Model model) {
    		ItemInfo item = itemService.getItemInfoById(itemId);
    		model.addAttribute("item", item);
    		return "item";
    	}
    	
    	@RequestMapping(value="/item/desc/{itemId}",produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")
    	@ResponseBody
    	public String getItemDesc(@PathVariable Long itemId) {
    		String itemDescById = itemService.getItemDescById(itemId);
    		return itemDescById;
    	}
    	
    	@RequestMapping(value="/item/param/{itemId}", produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")
    	@ResponseBody
    	public String getItemParam(@PathVariable Long itemId) {
    		String string = itemService.getItemParam(itemId);
    		return string;
    	}
    }
    

    结语

    最近看老马打斗地主,真相一拳👊干碎他的眼镜👀

    展开全文
  • 壹立方商城----实现商品搜索功能

    千次阅读 2018-10-20 12:56:28
    然后商品搜索页面就会展示,所有搜索到的商品(图片无法显示,是因为图片地址失效了,可以显示的是我自己添加的) 搜索时,会有关键字分词+高亮 还有分页效果 2.功能分析 我们在e3-portal-web首页展示中分析,...

    1.效果展示

    启动项目,进入淘淘商城首页,我们搜索小米

     

    然后商品搜索页面就会展示,所有搜索到的商品(图片无法显示,是因为图片地址失效了,可以显示的是我自己添加的)

    搜索时,会有关键字分词+高亮

    还有分页效果

    2.功能分析

    我们在e3-portal-web首页展示中分析,输入关键字后,点击搜索后到底发生了什么。

    由于搜索框是通用的,在搜索结果页面,上面也会有搜索框,所以搜索相关代码在header.jsp

    在header.jsp中,用户点击搜索,或者按回车(event.keyCode==13),会将id=key提交到search函数。search函数在header.jsp唯一引入的base-v1.js中

    我们搜索search函数,发现在第33行。encodeURIComponent(document.getElementById(a).value)获取到id=a(也就是key)的值,进行url编码就是"%xx%xxx"这种,然后拼接到"http://localhost:8085/search.html?q="后面。window.location.href表示跳转至url。

    所以我们知道,当用户点击搜索时,跳转"http://localhost:8085/search.html?q=xxx",并携带查询关键字q,所以我们只需要,接收关键字,从索引库查询即可。这里有个隐含的参数 "page页码",在搜索结果页面用于分页,在搜索页面仅仅是搜索,并不设置及

    ,所以默认page=1,搜索时默认搜索第一页。

    3.dao层

    3.1功能分析

    访问索引库的类。定义一些通用的数据访问方法。

    业务逻辑就是查询索引库。

    参数:SolrQuery对象

    业务逻辑:

    1. 根据Query对象进行查询。
    2. 返回查询结果。包括List<SearchItem>、查询结果的总记录数。

    需要把返回结果封装到pojo中,至少包含两个属性:List<SearchItem>、Long recordCount

    再包含一个总页数。

    创建如下SearchResult对象,放入e3-common中

    SearchResult.java

    package cn.e3mall.common.pojo;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class SearchResult implements Serializable {
    
    	private long recordCount;//总记录数
    	private int totalPages;//总页数
    	private List<SearchItem> itemList;//搜索结果列表
    	public long getRecordCount() {
    		return recordCount;
    	}
    	public void setRecordCount(long recordCount) {
    		this.recordCount = recordCount;
    	}
    	public int getTotalPages() {
    		return totalPages;
    	}
    	public void setTotalPages(int totalPages) {
    		this.totalPages = totalPages;
    	}
    	public List<SearchItem> getItemList() {
    		return itemList;
    	}
    	public void setItemList(List<SearchItem> itemList) {
    		this.itemList = itemList;
    	}
    	
    }
    

    3.2创建SearchDao

    由于搜索功能只在搜索工程中用到,可以不写接口,只写类。返回值:SearchResult

    在e3-search-service中创建com.taotao.search.dao包,在包中SearchDao创建用于访问索引库

    从service层接收封装好的SolrQuery查询索引库,获取QueryResponse,从QueryResponse获取SolrDocumentList,在从SolrDocumentList中获取solr业务域中的字段,并取出service层封装的高亮,封装成List<SearchItem>,放入SearchResult中
    SearchDao.java

    package cn.e3mall.search.dao;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.solr.client.solrj.SolrQuery;
    import org.apache.solr.client.solrj.SolrServer;
    import org.apache.solr.client.solrj.response.QueryResponse;
    import org.apache.solr.common.SolrDocument;
    import org.apache.solr.common.SolrDocumentList;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import cn.e3mall.common.pojo.SearchItem;
    import cn.e3mall.common.pojo.SearchResult;
    
    /**
     * 商品搜索dao
     * <p>
     * Title: SearchDao
     * </p>
     * 
     * @version 1.0
     */
    @Repository
    public class SearchDao {
    
    	@Autowired
    	private SolrServer solrServer;
    
    	/**
    	 * 根据SolrQuery查询索引库,封装SearchResult的itemList、recordCount
    	 * <p>
    	 * Title: search
    	 * </p>
    	 * <p>
    	 * Description:
    	 * </p>
    	 * 
    	 * @param query
    	 * @return
    	 */
    	public SearchResult search(SolrQuery query) throws Exception {
    		// 1、根据query查询索引库
    		QueryResponse queryResponse = solrServer.query(query);
    		// 2、获取商品列表
    		SolrDocumentList solrDocumentList = queryResponse.getResults();
    		// 3、取查询结果总记录数
    		long numFound = solrDocumentList.getNumFound();
    		SearchResult result = new SearchResult();
    		result.setRecordCount(numFound);
    		// 取商品列表,需要取高亮显示
    		Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
    		// 封装List<SearchItem>
    		List<SearchItem> itemList = new ArrayList<>();
    		for (SolrDocument solrDocument : solrDocumentList) {
    			SearchItem item = new SearchItem();
    			item.setId((String) solrDocument.get("id"));
    			item.setCategory_name((String) solrDocument.get("item_category_name"));
    			item.setImage((String) solrDocument.get("item_image"));
    			item.setPrice((long) solrDocument.get("item_price"));
    			item.setSell_point((String) solrDocument.get("item_sell_point"));
    			// 取高亮显示
    			List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
    			String title = "";
    			if (list != null && list.size() > 0) {
    				title = list.get(0);
    			} else {
    				title = (String) solrDocument.get("item_title");
    			}
    			item.setTitle(title);
    			// 添加到商品列表
    			itemList.add(item);
    		}
    		result.setItemList(itemList);
    		// 返回结果
    		return result;
    	}
    
    }
    

    4.service层

    4.1功能分析

    参数:queryString:查询条件

          Page:页码

          Rows:每页显示的记录数。

    业务逻辑:

    1. 创建一个SolrQuery对象。
    2. 设置查询条件
    3. 设置分页条件
    4. 需要指定默认搜索域。
    5. 设置高亮
    6. 执行查询,调用SearchDao。得到SearchResult
    7. 需要计算总页数。
    8. 返回SearchResult

    4.2创建service接口

    在e3-search-interface的SearchService创建接口

    SearchService.java

    package cn.e3mall.search.service;
    
    import cn.e3mall.common.pojo.SearchResult;
    
    public interface SearchService {
    	/**
    	 * 根据查询条件查询
    	 * @param queryString
    	 * @param page
    	 * @param rows
    	 * @return
    	 * @throws Exception
    	 */
    	SearchResult search(String keyword, int page, int rows)  throws Exception;
    }
    

    4.3创建service实现类

    在e3-search-service的cn.e3mall.search.service.impl包的SearchServiceImpl实现接口

    要注意注入searchDao依赖

    设置查询索引库的主查询条件和分页条件,还需要设置高亮,最后获取SearchResult封装总页数

    package cn.e3mall.search.service.impl;
    
    import org.apache.solr.client.solrj.SolrQuery;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import cn.e3mall.common.pojo.SearchResult;
    import cn.e3mall.search.dao.SearchDao;
    import cn.e3mall.search.service.SearchService;
    
    /**
     * 商品搜索Service
     * <p>
     * Title: SearchServiceImpl
     * </p>
     * 
     * @version 1.0
     */
    @Service
    public class SearchServiceImpl implements SearchService {
    
    	@Autowired
    	private SearchDao searchDao;
    
    	@Override
    	public SearchResult search(String keyword, int page, int rows) throws Exception {
    		// 创建一个SolrQuery对象
    		SolrQuery query = new SolrQuery();
    		// 设置查询条件
    		query.setQuery(keyword);
    		// 设置分页条件
    		if (page <= 0)
    			page = 1;
    		query.setStart((page - 1) * rows);
    		query.setRows(rows);
    		// 设置默认搜索域
    		query.set("df", "item_title");
    		// 开启高亮显示
    		query.setHighlight(true);
    		query.addHighlightField("item_title");
    		query.setHighlightSimplePre("<em style=\"color:red\">");
    		query.setHighlightSimplePost("</em>");
    		// 调用dao执行查询
    		SearchResult searchResult = searchDao.search(query);
    		// 计算总页数
    		long recordCount = searchResult.getRecordCount();
    		int totalPage = (int) (recordCount / rows);
    		if (recordCount % rows > 0)
    			totalPage++;
    		// 添加到返回结果
    		searchResult.setTotalPages(totalPage);
    		// 返回结果
    		return searchResult;
    	}
    
    }
    

    4.4applicationContext-service.xml

    dao层包扫描与发布service服务

    配置包扫面的时候,可以扩大包扫描的范围

    <!-- 配置包扫描器 -->
    <context:component-scan base-package="cn.e3mall.search" />
    <!-- 声明需要暴露的服务接口 发布服务 服务层暴露出来以后,表现层(web层)才能引用 -->
    <dubbo:service interface="cn.e3mall.search.service.SearchItemService" ref="searchItemServiceImpl" timeout="600000" />

    5.表现层

    5.1导入搜索结果静态页面

    5.2引入服务

    5.3创建controller


    请求的url:/search

    参数:

    1、q 查询条件。

    2、page 页码。默认为1

    返回值:

    逻辑视图,返回值。String。

    业务逻辑:

    接收参数
    调用服务查询商品列表
    把查询结果传递给页面。需要参数回显。
    在e3-search-web创建cn.e3mall.search.controller包,在cn.e3mall.search.controller创建SearchController

    cn.e3mall.search.controller.SearchController.java

    package cn.e3mall.search.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    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 cn.e3mall.common.pojo.SearchResult;
    import cn.e3mall.search.service.SearchService;
    
    /**
     * 商品搜索Controller
     * <p>
     * Title: SearchController
     * </p>
     * 
     * @version 1.0
     */
    @Controller
    public class SearchController {
    
    	@Autowired
    	private SearchService searchService;
    
    	@Value("${SEARCH_RESULT_ROWS}")
    	private Integer SEARCH_RESULT_ROWS;
    
    	@RequestMapping("/search")
    	public String searchItemList(String keyword, @RequestParam(defaultValue = "1") Integer page, Model model)
    			throws Exception {
    		//get请求中文乱码解决
    		keyword = new String(keyword.getBytes("iso-8859-1"), "utf-8");
    		// 查询商品列表
    		SearchResult searchResult = searchService.search(keyword, page, SEARCH_RESULT_ROWS);
    		// 把结果传递给页面
    		model.addAttribute("query", keyword);
    		model.addAttribute("totalPages", searchResult.getTotalPages());
    		model.addAttribute("page", page);
    		model.addAttribute("recourdCount", searchResult.getRecordCount());
    		model.addAttribute("itemList", searchResult.getItemList());
    
    		// 返回逻辑视图
    		return "search";
    	}
    }
    

    5.4配置分页大小

    分页大小放入配置文件中

    /e3-search-web/src/main/resources/conf/resource.properties

    #搜索结果每页显示的记录数
    SEARCH_RESULT_ROWS=60

    还需要在springmvc.xml加载配置文件

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:conf/resource.properties" />

    5.5测试

    发现无法翻页。

    翻页处理:在e3-search-web工程中:修改如下:

    修改url的端口,在这里可以看到前面说的page参数

    5.6图片无法显示
    这里说的是有图片的情况无法显示。

    数据库中保存的图片是以逗号分隔的url列表,只需要展示第一张图片即可。

    方法:

    1. 向索引库中添加文档时,只取第一张写入索引库
    2. 从文档列表转换为商品列表时可以取一张。
    3. 在jsp中对列表拆分,只取一张展示。

    可以在SearchItem中添加一个getImages方法:

    public String[] getImages() {
    		if(this.image != null&&!this.image.equals("")) {
    			String[] strings = this.image.split(",");
    			return strings;
    		}
    		return null;
    	}
    

    使用el表达式执行方法,获取第一张图片

     

     

     

     

     

     

    参考文章

    原文:https://blog.csdn.net/pdsu161530247/article/details/81974760

    展开全文
  • (3)商品搜索(搜索内容进行分词,提取关键字,模糊查询)。(4) QQ在线咨询功能。本项目基本实现完整的B2C网站的功能。二,项目部署:本项目使用Eclipse_EE + Tomcat7.0 + MySql5.6的开发环境。1,安装Eclipse_EE...
  • solr实现商品搜索功能和安装

    千次阅读 2018-10-06 11:06:14
    Solr简介 用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成...同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善...

    Solr简介

    用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果;

    折叠编辑本段Solr引擎

    Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。

    折叠编辑本段Solr特点

    文档通过Http利用XML 加到一个搜索集合中。查询该集合也是通过http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。

    搜索实现的原理

    网络爬虫(网络蜘蛛)去各个网站上抓取网页,然后保存到服务器上,通过分词器,分析网页中的出现最多的关键词,按照词出现的次数进行排名。当我们搜索,实际上就是关键词出现的次数最多对应的网页的排名。

    solr的工作机制:

    1、solr就是在lucene工具包的基础之上进行了封装,而且是以web服务的形式对外提供索引功能

    2、业务系统需要使用到索引的功能(建索引,查索引)时,只要发出http请求,并将返回数据进行解析即可

    Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。

    Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

    为什么要用solr服务,为什么要用luncence?

    问题提出:当我们访问购物网站的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据不可能是根据数据库的字段查询的,那是怎么查询出来的呢,为什么千奇百怪的关键字都可以查询出来呢?

    答案就是全文检索工具的实现,luncence采用了词元匹配和切分词。举个例子:北京天安门------luncence切分词:北京  京天  天安  安门  等等这些分词。所以我们搜索的时候都可以检索到。

    有一种分词器就是IKAnalyzer中文分词器,它有细粒度切分和智能切分,即根据某种智能算法。

    这就使用solr的最大的好处:检索功能的实现。

    使用步骤;

    (1)solr服务器搭建,因为solr是用java5开发的,所以需要jdk和tomcat。搭建部署

    (2)搭建完成后,我们需要将要展示的字段引入solr的库中。配置spring与solr结合,工程启动的时候启动solr

    (3)将数据库中的查询内容导入到solr索引库,这里使用的是solrj的客户端实现的。具体使用可以参考api

    (4)建立搜索服务,供客户端调用。调用solr,查询内容,这中间有分页功能的实现。solr高亮显示的实现。

    (5)客户端接收页面的请求参数,调用搜索服务,进行搜索。

    业务字段判断标准:

    1、在搜索时是否需要在此字段上进行搜索。例如:商品名称、商品的卖点、商品的描述

    (这些相当于将标签给了solr,导入商品数据后,solr对这些字段的对应的商品的具体内容进行分词切分,然后,我们就可以搜索到相关内容了)

    2、后续的业务是否需要用到此字段。例如:商品id。

    需要用到的字段:

    1、商品id

    2、商品title

    3、卖点

    4、价格

    5、商品图片

    6、商品分类名称

    7、商品描述

    Solr中的业务字段:

    1、id——》商品id

    其他的对应字段创建solr的字段。

    <field name="item_title" type="text_ik" indexed="true" stored="true"/>

    <field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>

    <field name="item_price"  type="long" indexed="true" stored="true"/>

    <field name="item_image" type="string" indexed="false" stored="true" />

    <field name="item_category_name" type="string" indexed="true" stored="true" />

    <field name="item_desc" type="text_ik" indexed="true" stored="false" />

     

    <field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>

    <copyField source="item_title" dest="item_keywords"/>

    <copyField source="item_sell_point" dest="item_keywords"/>

    <copyField source="item_category_name" dest="item_keywords"/>

    <copyField source="item_desc" dest="item_keywords"/>

    重新启动tomcat

    Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。

    Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务。有效降低频繁访问数据库对数据库造成的压力。

    第一步:将solr部署在linux系统下。

    第二步:solrJ是solr的客户端,使用它需要依赖solrJ的jar包。

    第三步:将数据库的内容添加到solr的索引库,这样查询就在索引库查询,而不是数据库了。

    controller层:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    @Controller

    @RequestMapping("/manager")

    public class ItemController {

     @Autowired

     private ItemService itemService;

     @RequestMapping("/importall")

     @ResponseBody

      public   TaotaoResult importAllItem(){

                TaotaoResult result= itemService.importAllItem();

                return result;

     }

    }<br>service层编写:<br>多表查询商品,显示在页面的逻辑编写:<br>mapper.java

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    package com.taotao.search.mapper;

     

    import java.util.List;

     

    import com.taotao.search.pojo.Item;

     

    public interface ItemMapper {

        List<item> getItemList();

     

    }

    </item>

      mapper.xml

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

    "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

    <mapper namespace="com.taotao.search.mapper.ItemMapper">

    <select id="getItemList" resultType="com.taotao.search.pojo.Item">

        SELECT

        a.id,

        a.title,

        a.sell_point,

        a.price,

        a.image,

        b. NAME category_name

        FROM

        tb_item a

        LEFT JOIN tb_item_cat b ON a.cid = b.id

    </select>

    </mapper>

    第四步:从索引库查询的逻辑编写:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    //从索引库里面获取商品信息,现在这个dao层是从索引库获取信息,因为之前的写的逻辑是将db里面的数据导入到索引库。后面的查询都是从索引库中进行,而不从数据库了

    @Repository

    public class SearchDaoImpl implements SearchDao {

        @Autowired

        private SolrServer solrServer;

     

        @Override

        public SearchResult search(SolrQuery query) throws Exception {

            //这是从索引库里面,直接执行查询

            QueryResponse response = solrServer.query(query);

            //获取查询的结果

            SolrDocumentList documentList= response.getResults();

             

            SearchResult result=new SearchResult();

            //这是获取总记录数

            result.setRecordCount(documentList.getNumFound());

             

            List<Item> itemList=new ArrayList<>();

            //商品的高亮显示,即当鼠标移到字上时,该字体变色,这是从QueryResponse中获取的

            Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

             

            for (SolrDocument solrDocument : documentList) {

                 

                //每个SolrDocument都是一个商品pojo的内容,所以这里要创建一个商品的pojo对象,来获取详细的字段

                Item item=new Item();

                item.setId((String) solrDocument.get("id"));

                //高亮显示是title的高亮显示

                List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");

                String title="";

                if (list!=null && list.size()>0) {

                    title=list.get(0); 

                }

                else{

                    title=(String) solrDocument.get("item_title"); 

                }

             

                item.setTitle(title);

                item.setPrice((Long) solrDocument.get("item_price"));

                item.setImage((String) solrDocument.get("item_image"));

                item.setCategory_name((String) solrDocument.get(" item_category_name"));

                item.setSell_point((String) solrDocument.get("item_sell_point"));

               itemList.add(item);

            }

             

              result.setItemList(itemList);

         

            return result;

        }

     

    }

    第五步:索引库内容建立好后,开始编写对外的服务接口,即通过条件搜索具体的商品,比如手机,会显示出总共的手机列表信息,第几页,总共多少页,总共多少个搜索结果

    ******************************************************************************************************************************************************

    Solr和lucene区别

    Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文检索引擎,Lucene提供了完整的查询引擎和索引引擎,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者以Lucene为基础构建全文检索引擎。

    Solr的目标是打造一款企业级的搜索引擎系统,它是一个搜索引擎服务,可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。

    Solr的下载

    clip_image002

    http://lucene.apache.org/

    最新版:5.3.1

    本课程的版本:4.10.3

    clip_image004

    Solr的安装及配置

    clip_image006

    安装solr,就是去部署它的war包,war包所在的位置如图:

    clip_image008

    开发环境

    Jdk:1.7以上。1.7.0_72

    Tomcat:7以上。apache-tomcat-7.0.53

    Solr:4.10.3

    Solr集成tomcat

    第一步:安装tomcat,建议安装一个全新的tomcat。

    第二步:上传solr安装压缩包到服务器上,然后解压

    unzip -q /root/solr-4.10.3.zip

    第三步:在tomcat的webapps中事先建立一个solr工程文件夹

    mkdir /usr/local/apache-tomcat-7.0.63/webapps/solr

    然后将solr的war包解压到solr工程文件夹里面去

    unzip /root/solr-4.10.3/dist/solr-4.10.3.war -d /usr/local/apache-tomcat-7.0.63/webapps/solr

    然后,将日志工具jar包添加到solr的war工程的WebInf的lib中

    cp /root/solr-4.10.3/example/lib/ext/*.jar /usr/local/apache-tomcat-7.0.63/webapps/solr/WEB-INF/lib/

    第四步:从solr的安装目录中拷贝一个示例solrhome到我们的服务器真实部署目录中

    拷贝: cp -r /root/solr-4.10.3/example/solr /usr/local/

    改名: mv /usr/local/solr/ /usr/local/solrhome

    第五步:告诉solr的war工程,我们准备的solrhome目录所在的路径

    vi /usr/local/apache-tomcat-7.0.63/webapps/solr/WEB-INF/web.xml

    clip_image010

    至此,可以启动tomcat,进行测试

    了解solrhome

    1、collection1:是一个solrcore,一个solrcore就是一个索引库。一个solr服务器上可以有多solrcore。每个索引库之间是相互独立的。

    2、\solrhome\collection1\conf:是存放每个solrcore的个性配置。

    clip_image012

    3、Solrconfig.xml

    a) luceneMatchVersion:匹配lucene的版本信息

    b) Lib:solrcore扩展使用的jar包。默认值是collection1\lib,如果没有此文件夹就创建一个。

    c) dataDir:索引库存放的目录。默认是collection1\data文件夹。如果没有solr会自动创建。如果想修改为其他位置,需要配置此节点。

    d) requestHandler:配置solr对外提供服务的url

    i. <requestHandler name="/select" class="solr.SearchHandler">:查询索引库使用的url

    ii. <requestHandler name="/update" class="solr.UpdateRequestHandler">

    维护索引库使用的url

    e) defaultQuery:管理页面默认的查询条件 *:*

    4、Core.properties:配置了solrcore的名字。

    第六步:告诉solr工程solrhome的位置。修改solr/WEB-INF/web.xml文件。

    clip_image014

    第七步:启动tomcat

    访问http://localhost:8080/solr

    clip_image016

    管理界面功能介绍

    Core Admin

    solrcore的管理 功能。

    添加一个solrcore

    添加步骤:

    第一步:把collection1复制一份改名为collection2

    第二步:修改core.properties。name=collection2

    第三步:重启tomcat

    clip_image018

    Core Selecter

    选择要管理哪个solrcore。

    clip_image020

    Analysis

    clip_image022

    查看域的分词效果。

    Dataimport

    可以实现把数据库中的数据导入到索引库中。

    clip_image024

    Documents

    索引库维护功能。

    增删改查

    clip_image026

    Query

    索引查询功能。

    clip_image028

    索引的维护

    在solr中域必须先定义后使用。而且每个document中必须有一个id域。

    Schema.xml

    Field:域的定义。

    Name:域的名称

    Type:域的类型

    Indexed:是否索引

    Stored:是否存储

    multiValued:是否多值,如果是多值在一个域中可以保持多个值。

    dynamicField动态域

    Name:域的名称,是一个表达式。如果域的名称和表达式相匹配,此域名就可以使用。

    Type:域的类型

    Indexed:是否索引

    Stored:是否存储

    multiValued:是否多值,如果是多值在一个域中可以保持多个值。

    uniqueKey

    每个文档必须有一个uniqueKey,而且不能重复。相当于表中的主键。

    copyField

    复制域。

    Source:源域

    Dest:目标域。

    创建文档时,solr会自动把源域的内容复制到目标域。使用复制域可以提供查询的性能。

    fieldType

    域的类型。

    Name:域类型名。

    Class:对应的实现类。solr.TextField类似于Lucene中的TextField。可以配置用户自定义的分析器。

    自定义fieldType使用中文分析器

    配置中文分析器

    配置步骤:

    第一步:把IKAnalyzer2012FF_u1.jar添加到solr工程的lib库中。

    第二步:把配置文件和扩展词典、停用词词典添加到solr工程classpath下。Solr/WEB-INF/classes。保证字典的字符集是utf-8.

    配置自定义fieldtype

    在schema.xml中添加如下内容:

    <!-- IKAnalyzer-->

    <fieldType name="text_ik" class="solr.TextField">

    <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

    </fieldType>

    <!--IKAnalyzer Field-->

    配置自定义的域

    <field name="title_ik" type="text_ik" indexed="true" stored="true" />

    <field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/>

    重启tomcat,查看效果

    clip_image030

    淘淘商城商品信息搜索域定义

    <!--product-->

    <field name="product_name" type="text_ik" indexed="true" stored="true"/>

    <field name="product_price" type="float" indexed="true" stored="true"/>

    <field name="product_description" type="text_ik" indexed="true" stored="false" />

    <field name="product_picture" type="string" indexed="false" stored="true" />

    <field name="product_catalog_name" type="string" indexed="true" stored="true" />

    <field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>

    <copyField source="product_name" dest="product_keywords"/>

    <copyField source="product_description" dest="product_keywords"/>

    添加文档

    clip_image032

    注意:每个文档必须有一个id域。而且域名必须在schema.xml中定义。

    Dataimport插件

    可以批量把数据库中的数据导入到索引库中。

    需要的jar包

    clip_image034

    安装步骤:

    第一步:把dataimport插件依赖的jar包添加到collection1\lib文件夹下。

    第二步:把mysql的数据库驱动也放到collection1\lib文件夹下

    第三步:修改solrhome/collection1/conf/solrconfig.xml,添加一个requestHandler。

    <requestHandler name="/dataimport"

    class="org.apache.solr.handler.dataimport.DataImportHandler">

    <lst name="defaults">

    <str name="config">data-config.xml</str>

    </lst>

    </requestHandler>

    第四步:创建一个data-config.xml。目录和solrconfig.xml在同一个目录下collection1\conf。

    <?xml version="1.0" encoding="UTF-8" ?>

    <dataConfig>

    <dataSource type="JdbcDataSource"

    driver="com.mysql.jdbc.Driver"

    url="jdbc:mysql://192.168.33.10:3306/taotao"

    user="root"

    password="root"/>

    <document>

    <entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products ">

    <field column="pid" name="id"/>

    <field column="name" name="product_name"/>

    <field column="catalog_name" name="product_catalog_name"/>

    <field column="price" name="product_price"/>

    <field column="description" name="product_description"/>

    <field column="picture" name="product_picture"/>

    </entity>

    </document>

    </dataConfig>

    第五步:重启tomcat后,进入solr管理页面,执行数据导入

    clip_image036

    索引库的查询

    查询语法支持的参数

    q:主查询条件。完全支持lucene语法。还进行了扩展。

    fq:过滤查询。是在主查询条件查询结果的基础上进行过滤。

    sort:排序条件。排序的域asc。如果有多个排序条件使用半角逗号分隔。

    start, rows:分页处理。Start起始记录rows每页显示的记录条数。

    fl:返回结果中域的列表。使用半角逗号分隔。

    df:默认搜索域

    wt:响应结果的数据格式,可以是json、xml等。

    hl:开启高亮显示。

    hl.fl:要高亮显示的域。

    hl.simple.pre:高亮显示的前缀

    hl.simple.post:高亮显示的后缀

    SolrJ客户端

    可以实现对索引库的增删改查操作。

    使用步骤:

    第一步:创建一java工程。

    第二步:导入jar包。导入solrj的jar 包。

    clip_image038

    clip_image040

    索引库的维护

    添加文档

    第1步:创建SolrServer对象和服务端建立连接。HttpSolrServer子类来完成。集群环境使用CloudSolrServer。

    第2步:创建一文档对象。SolrInputDocument。

    第3步:向文档对象中添加域。使用addField添加域。要求必须有id域,而且每个域必须在schema.xml中定义。

    第4步:使用solrServer对象把文档提交到服务器。

    代码实现

    clip_image042

    //添加文档对象

    @Test

    public void addDocument() throws Exception {

    //创建一个SolrServer对象

    //参数:solr服务器的url

    SolrServer server = new HttpSolrServer("http://localhost:8080/solr");

    //创建文档对象

    SolrInputDocument document = new SolrInputDocument();

    //添加域

    document.addField("id", "num001");

    document.addField("title_ik", "巧手DIY彩帘");

    //把document对象写入索引库

    server.add(document);

    //提交修改

    server.commit();

    }

    删除文档

    根据id删除文档

    //根据id删除文档

    @Test

    public void deleteDocumentById() throws Exception {

    SolrServer server = new HttpSolrServer("http://localhost:8080/solr");

    //删除文档

    server.deleteById("num001");

    //提交修改

    server.commit();

    }

    根据查询删除文档

    //根据查询删除文档

    @Test

    public void deleteDocumentByQuery() throws Exception {

    SolrServer server = new HttpSolrServer("http://localhost:8080/solr");

    //根据查询条件删除

    server.deleteByQuery("*:*");

    //提交修改

    server.commit();

    }

    修改文档

    Solrj并没有一个方法可以修改文档。还是使用add方法。只需要添加一个新的文档,保证新文档的id和被修改文档的id一致即可。

    本质先删除后添加。

    查询索引库

    实现步骤

    第一步:创建一个solrServer对象。

    第二步:创建一个solrQuery对象。

    第三步:向solrQuery对象中添加查询条件。

    第四步:执行查询。返回文档列表。

    第五步:遍历列表。

    代码实现

    //简单查询

    @Test

    public void queryIndex() throws Exception {

    SolrServer server = new HttpSolrServer("http://localhost:8080/solr");

    //创建一个查询对象

    SolrQuery query = new SolrQuery();

    //添加查询条件

    //query.setQuery("*:*");

    query.set("q", "*:*");

    //执行查询

    QueryResponse response = server.query(query);

    //取文档列表

    SolrDocumentList solrDocumentList = response.getResults();

    System.out.println("查询结果的总数量:" + solrDocumentList.getNumFound());

    //遍历列表

    for (SolrDocument solrDocument : solrDocumentList) {

    System.out.println(solrDocument.get("id"));

    System.out.println(solrDocument.get("product_name"));

    System.out.println(solrDocument.get("product_price"));

    System.out.println(solrDocument.get("product_catalog_name"));

    System.out.println(solrDocument.get("product_picture"));

    }

    }

    综合案例

    需求

    使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格范围搜索商品信息,也可以根据价格进行排序。

    需求分析

    开发需要的文档

    1、数据库的表结构。

    2、页面原型图。

    3、业务流程图

    页面原型分析

    clip_image044

    流程图

    clip_image045

    Dao层

    功能:查询solr服务返回一个商品列表。需要一个query对象,执行query对象进行查询,返回商品列表。

    参数:SolrQuery query

    返回值:ResultModel 包含商品列表

    商品的pojo:

    public class ProductModel {

    // 商品编号

    private String pid;

    // 商品名称

    private String name;

    // 商品分类名称

    private String catalog_name;

    // 价格

    private float price;

    // 商品描述

    private String description;

    // 图片名称

    private String picture;

    }

    返回值Pojo:

    public class ResultModel {

    // 商品列表

    private List<ProductModel> productList;

    // 商品总数

    private Long recordCount;

    // 总页数

    private int pageCount;

    // 当前页

    private int curPage;

    }

    方法定义:

    ResultModel queryProduct(SolrQuery query) throws Exception;

    Service

    功能:接收controller传递过来的参数。创建一SolrQuery对象,拼装查询条件调用Dao层执行查询返回一个ResultModel对象。还需要计算商品列表的总页数。

    参数:

    1、查询条件:String queryString

    2、商品分类名称:String catalog_name

    3、价格区间过滤条件:使用一个字符串来描述一个区间例如:

    *-10,10-20,20-30,30-*。

    String price

    4、排序条件:只需要接收一个排序的方式就可以了。0:升序1:降序。 String sort

    5、分页条件:接收一个页码是一个Integer数据。需要我们确定每页显示商品的数量。可以定义在常量或者配置文件。每页显示60商品。Integer page

    返回值:ResultModel

    方法定义:

    ResultModel queryProduct(String queryString, String catalog_name, String price,String sort, Integer page);

    Controller

    功能:接收页面传递过来的参数,调用service查询商品列表。把查询结果传递给页面。还需要参数回显。

    参数:

    1. 查询条件:String queryString

    2. 商品分类名称:String catalog_name

    3. 价格区间过滤条件:使用一个字符串来描述一个区间例如:

    *-10,10-20,20-30,30-*。

    String price

    4. 排序条件:只需要接收一个排序的方式就可以了。0:升序1:降序。 String sort

    5. 分页条件:接收一个页码是一个Integer数据。需要我们确定每页显示商品的数量。可以定义在常量或者配置文件。每页显示60商品。Integer page

    6、Model,传递参数使用。

    返回值:String(逻辑视图名)

    方法定义:

    Public String queryProduct(String queryString, String catalog_name, String price,String sort, Integer page, Model model)

    Jsp

    clip_image047

    代码实现

    实现步骤

    第一步:创建一web工程

    第二步:导入jar包。需要springmvc、spring、solrj、solrj依赖的jar、日志相关的jar包。

    第三步:编写dao

    第四步:编写Service

    第五步:编写Controller

    第六步:配置前端控制器,创建springmvc.xml配置三大件。

    代码实现

    Dao

    @Repository

    public class ProductDaoImpl implements ProductDao {

    @Autowired

    private SolrServer solrServer;

    @Override

    public ResultModel queryProduct(SolrQuery query) throws Exception {

    //根据query对象查询索引库

    QueryResponse response = solrServer.query(query);

    //取商品列表

    SolrDocumentList documentList = response.getResults();

    List<ProductModel> productList = new ArrayList<>();

    for (SolrDocument solrDocument : documentList) {

    //取商品信息

    ProductModel productModel = new ProductModel();

    productModel.setPid((String) solrDocument.get("id"));

    //取高亮显示

    String productName = "";

    Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

    List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");

    if (list != null && list.size() > 0) {

    productName = list.get(0);

    else {

    productName = (String) solrDocument.get("product_name");

    }

    productModel.setName(productName);

    productModel.setCatalog_name((String) solrDocument.get("product_catalog_name"));

    productModel.setPrice((float) solrDocument.get("product_price"));

    productModel.setPicture((String) solrDocument.get("product_picture"));

    //添加到商品列表

    productList.add(productModel);

    }

    //返回值对象

    ResultModel resultModel = new ResultModel();

    resultModel.setProductList(productList);

    //查询结果总数量

    resultModel.setRecordCount(documentList.getNumFound());

    return resultModel;

    }

    }

    Service

    @Service

    public class ProductServiceImpl implements ProductService {

    @Autowired

    private ProductDao productDao;

    @Override

    public ResultModel queryProduct(String queryString, String catalog_name,

    String price, String sort, Integer page) throws Exception {

    //拼装查询条件

    SolrQuery solrQuery = new SolrQuery();

    //查询条件

    if (null != queryString && !"".equals(queryString)) {

    solrQuery.setQuery(queryString);

    else {

    solrQuery.setQuery("*:*");

    }

    //分类名称过滤条件

    if (null != catalog_name && !"".equals(catalog_name)) {

    solrQuery.addFilterQuery("product_catalog_name:" + catalog_name);

    }

    //价格区间过滤条件

    if (null != price && !"".equals(price)) {

    String[] strings = price.split("-");

    solrQuery.addFilterQuery("product_price:["+strings[0]+" TO "+strings[1]+"]");

    }

    //排序条件

    if ("1".equals(sort)) {

    solrQuery.setSort("product_price", ORDER.desc);

    else {

    solrQuery.setSort("product_price", ORDER.asc);

    }

    //分页条件

    if (page == null) page = 1;

    int start = (page - 1) * Global.PAGE_SIZE;

    solrQuery.setStart(start);

    solrQuery.setRows(Global.PAGE_SIZE);

    //设置默认搜索域

    solrQuery.set("df", "product_keywords");

    //高亮显示

    solrQuery.setHighlight(true);

    //高亮显示的域

    solrQuery.addHighlightField("product_name");

    //前缀

    solrQuery.setHighlightSimplePre("<span style=\"color:red\">");

    //后缀

    solrQuery.setHighlightSimplePost("</span>");

    //执行查询

    ResultModel resultModel = productDao.queryProduct(solrQuery);

    //计算总页数

    Long recordCount = resultModel.getRecordCount();

    int pageCount = (int) (recordCount / Global.PAGE_SIZE);

    if (recordCount % Global.PAGE_SIZE > 0) {

    pageCount ++;

    }

    resultModel.setPageCount(pageCount);

    resultModel.setCurPage(page);

    return resultModel;

    }

    }

    Controller

    @Controller

    public class ProductController {

    @Autowired

    private ProductService productService;

    @RequestMapping("/list")

    public String queryProduct(String queryString, String catalog_name,

    String price, String sort, Integer page, Model model) {

    // 查询商品列表

    ResultModel resultModel = null;

    try {

    resultModel = productService.queryProduct(queryString,

    catalog_name, price, sort, page);

    catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    // 传递给页面

    model.addAttribute("result", resultModel);

    // 参数回显

    model.addAttribute("queryString", queryString);

    model.addAttribute("catalog_name", catalog_name);

    model.addAttribute("price", price);

    model.addAttribute("sort", sort);

    model.addAttribute("page", page);

    // 返回jsp

    return "product_list";

    }

    }

    Springmvc

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

    http://www.springframework.org/schema/mvc

    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.1.xsd

    http://www.springframework.org/schema/aop

    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

    <!-- 配置扫描包 -->

    <context:component-scan base-package="cn..jd" />

    <!-- 配置注解驱动 -->

    <mvc:annotation-driven />

    <!-- jsp视图解析器 -->

    <bean

    class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <!-- 前缀 -->

    <property name="prefix" value="/WEB-INF/jsp/"></property>

    <!-- 后缀 -->

    <property name="suffix" value=".jsp"></property>

    </bean>

    <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">

    <constructor-arg value="http://localhost:8080/solr/"></constructor-arg>

    </bean>

    </beans>

    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"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

    id="WebApp_ID" version="2.5">

    <display-name>SolrJD0508</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>

    <!-- 配置前端控制器 -->

    <!-- SpringMVC配置 -->

    <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>

    </servlet>

    <servlet-mapping>

    <servlet-name>springmvc</servlet-name>

    <url-pattern>*.action</url-pattern>

    </servlet-mapping>

    <filter>

    <filter-name>Character Encoding</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>Character Encoding</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

    </web-app>

    展开全文
  • Django+Vue开发生鲜电商平台之8.商品详情页功能实现

    千次阅读 多人点赞 2020-07-29 21:35:37
    用户收藏功能需要先定义序列化进行验证,添加收藏时添加到当前用户下,可以添加、列举和删除收藏,还需要限制同一用户对同一商品只能收藏一次;实现权限验证,限制用户只能操作自己的收藏,进行局部定义;结合前端...
  • 在taotao-search-web工程需要添加对Search服务的引用,如下图所示。  springmvc.xml文件所有代码如下: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmln
  • 淘淘商城第九天    讲师:入云龙 今天的内容: ...实现商品搜索功能。 2、点击商品的图片,打开商品详情页面 a) 商品基本信息 b) 延迟加载商品详情。延迟一秒加载使用ajax c) 商品的规格参数。按
  • 主要为大家详细介绍了JavaWeb实现简单查询商品功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 上一篇:JAVA_WEB项目之Lucene检索框架入门案例初步给出了一个r
  • l搜索功能实现 1.1.系统架构 2.Solr概述 2.1.什么是Solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可...
  • 之前我们就差不多把商品搜索功能实现了,本文我们来一起测试下该搜索功能。 首先我们要保证zookeeper、redis、image、solr服务都开启。接着我们把taotao-common工程重新打包到本地maven仓库,由于taotao-search-...
  • 实现的添加购物商品,删除购物商品并且显示购物车信息。 1. 在自己建立的WEB工程中,建立包shopcart.dto,在相应的包中添加类Product.java ,ShopCart.java/*类Product */package shopcart.dto;import java.io....
  • 搜索功能实现   1.1. 系统架构 2. Solr概述 2.1.什么是Solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了...
  • 上一节我们完成了使用DataGrid显示所有商品信息,这节我们开始添加几个功能:添加、更新、删除和查询。首先我们实现下前台的显示,然后再做后台获取数据。 1. 添加、更新、删除和查询功能的前台实现  DataGrid...
  • Web页面中经常需要实现如图5-2所示的级联菜单的效果。即根据用户的选择,动态展开并显示出对应选项子菜单中的内容。本例中是根据用户所选择的商品类别信息,在子菜单中显示对应的商品名称。图5-2 级联菜单的效果...
  • 实现商品分类和品牌管理功能

    千次阅读 2020-02-23 15:27:23
    文章目录一、实现商品分类管理1.1 导入数据1.2 实体类1.3 controller1.4 service1.5 mapper1.6.启动并测试二、跨域问题2.1 cors解决跨域2.1.1 简单请求2.1.2 特殊请求2.2 cors跨域的实现过程三、实现商品品牌管理3.1...
  • 系统完成的主要功能有:用户设置功能、发布信息功能、信息管理功能搜索信息功能,留言功能,及系统管理功能,具体业务功能包括如下: 用户注册:学生可利用自已学号进行注册,注册实现实名制。 用户登录:只有登录...
  • 功能一:实现商品分类查询 1、首先导入项目的SQL:有需要的可以加我Q514742768,导入到Navicat中,因为要做商品分类的查询,首先来看看商品分类的表: CREATE TABLE `tb_category` ( `id` bigint(20) NOT NULL ...
  • springboot+elasticsearch实现一个搜索引擎的功能 一、elasticsearch的安装 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java...
  • 交互功能只写了一部分,仅供学习参考。如想下载源码,请移步https://github.com/guozi007a/taobao-homepage.git我传到github上了。在这个页面点Code选项,下载压缩包即可。 老规矩:直接上货,先看效果图~~ 上传的...
  • 学习vue+element做用户条件分页查询遇到的坑! ps:(table :data 直接使用 list整个对象赋值,纯前端分页功能实现)!
  • 实现PHPWEB系统 商品页面 图片放大镜功能 附有安装说明,安装前请注意备份
  • 系统在自己一步一步部署下完成站内搜索,可以了解Solr集合SpringMvc的使用,对Solr安装使用可以提升许多,我还有一篇文展描述了步骤, 配置完好的solr(中文分析器)+我配置的SolrHome+mysql的数据库+javaweb程序 希望...
  • web实现全景图的交互展示

    千次阅读 2020-08-21 03:40:00
    Web实现全景图的交互展示不需要学习其他知识,小白也能实现全景图AR展示一、webVR全景图多种方案实现(aframe,Krpano,three,jquery-vrview等等)二、用krpano之前的一些知识准备三、krpano的购买、下载、注册四、...
  • 注释掉(这个的功能类似百度的竞价排名): 8、 启动solr: java -Dsolr.solr.home=taotao-solr -jar start.jar 测试: 添加IK中文分词器的支持 1、 将IKAnalyzer-2012-4x.jar拷贝到example\...
  • 在学习了Redis&amp;Spring-Data-Redis入门和Solr&amp;Spring-Data-Solr入门后,接...手摸手教你优雅的实现电商项目中的Solr搜索功能,整合SSM框架和Shiro安全框架;教你用Vue.JS和ElementUI写出超漂亮的页...
  • Web层涉及到的技术: 前端交互:页面之间的交互和交互细节 Restful:前端设计接口之间的一种常用的规范 Spring MVC:框架整合,以及如何应用设计和实现Restful接口 Bootstrap和jquery:前者负责页面布局和样式控制...
  • 电商项目笔记之四:搜索功能实现

    千次阅读 2012-12-25 23:55:07
    这里边先检查了一下传值是否为空 ,为空也并不是错误 因为直接点网页上的"搜索" 就去显示最新商品好了 image是一个Map ,这个map存储了跳转后的背景图片, 这个情况下 主页的主显示区的背景图片被设置成"搜索结果是XX...
  • 实现主页、按条件搜索商品商品详情、评论商品、收藏、商品后台管理等等完整功能,可用作毕业设计,提供对应毕业设计报告范文可用作参考修改,工程文档以及完整报告私聊扣扣, 三一2625138,附带环境安装和程序运行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,789
精华内容 9,915
关键字:

web商品搜索功能实现