淘淘商城35-商品搜索之商品搜索功能实现

版权声明:本文为博主原创文章,如有转载请注明出处,谢谢。 https://blog.csdn.net/pdsu161530247/article/details/81974760

目录

1.效果展示

2.功能分析

3.dao层

3.1功能分析

3.2创建SearchDao

4.service层

4.1功能分析

4.2创建service接口

4.3创建service实现类

4.4applicationContext-service.xml

5.表现层

5.1导入搜索结果静态页面

5.2引入服务

5.3创建controller

5.4配置分页大小

5.5测试

5.6图片无法显示


1.效果展示

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

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

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

还有分页效果

2.功能分析

我们在taotao-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对象,放入taotao-common中

package com.taotao.common.pojo;

import java.io.Serializable;
import java.util.List;
/**
 * 商品搜索的分页信息结果对象
 * @author Administrator
 *
 */
public class SearchResult implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private List<SearchItem> itemList;// 搜索结果列表
	private long recordCount;// 总记录数
	private long pageCount;// 总页数
	public List<SearchItem> getItemList() {
		return itemList;
	}
	public void setItemList(List<SearchItem> itemList) {
		this.itemList = itemList;
	}
	public long getRecordCount() {
		return recordCount;
	}
	public void setRecordCount(long recordCount) {
		this.recordCount = recordCount;
	}
	public long getPageCount() {
		return pageCount;
	}
	public void setPageCount(long pageCount) {
		this.pageCount = pageCount;
	}

}

3.2创建SearchDao

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

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

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

package com.taotao.search.dao;

import java.util.LinkedList;
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 com.taotao.common.pojo.SearchItem;
import com.taotao.common.pojo.SearchResult;

@Repository
public class SearchDao {
	
	@Autowired
	private SolrServer solrServer;
	/**
	 * 根据SolrQuery查询索引库,封装SearchResult的itemList、recordCount
	 * @param query
	 * @return
	 * @throws Exception 
	 */
	public SearchResult search(SolrQuery query) throws Exception {
		//1.根据query对象查询索引库
		QueryResponse response = solrServer.query(query);
		//2.获取商品列表
		SolrDocumentList solrDocumentList = response.getResults();
		//3.封装List<SearchItem>
		List<SearchItem> itemList = new LinkedList<SearchItem>();
		for (SolrDocument solrDocument : solrDocumentList) {
			//3.1封装SearchItem
			SearchItem item = new SearchItem(); 
			System.out.println(solrDocument.get("id").toString());
			item.setId(Long.parseLong(solrDocument.get("id").toString()));
			item.setCategory_name(solrDocument.get("item_category_name").toString());
			item.setImage(solrDocument.get("item_image").toString());
			item.setPrice((Long)solrDocument.get("item_price"));
			item.setSell_point(solrDocument.get("item_sell_point").toString());
			//item_desc商品内容不显示,不用设置
			
			//3.2取高亮,高亮由service设置
			Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
			List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
			String itemTitle = "";
			//有高亮显示的内容时。
			if(list != null && list.size() > 0) {
				itemTitle = list.get(0);
			}else {
				itemTitle = solrDocument.get("item_title").toString();
			}
			item.setTitle(itemTitle);
			//3.3将SearchItem添加到List<SearchItem>
			itemList.add(item);
		}
		//4.封装SearchResult返回
		SearchResult result = new SearchResult();
		//4.1商品列表
		result.setItemList(itemList);
		//4.2商品总数
		result.setRecordCount(solrDocumentList.getNumFound());
		return result;
	}
}

4.service层

4.1功能分析

参数:queryString:查询条件

      Page:页码

      Rows:每页显示的记录数。

业务逻辑:

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

4.2创建service接口

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

/**
	 * 根据查询条件查询
	 * @param queryString
	 * @param page
	 * @param rows
	 * @return
	 * @throws Exception
	 */
	SearchResult search(String queryString,Integer page,Integer rows) throws Exception;

4.3创建service实现类

在taotao-search-service的com.taotao.search.service.impl包的SearchServiceImpl实现接口

要注意注入searchDao依赖

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

/**
	 * 封装查询条件,调用dao。
	 * 封装SearchResult的pageCount,返回SearchResult
	 */
	@Override
	public SearchResult search(String queryString, Integer page, Integer rows) throws Exception {
		//1.创建solrQuery对象
		SolrQuery query = new SolrQuery();
		//2.设置主查询条件
		query.setQuery(queryString);
		//3.设置分页条件
		query.setStart((page-1)*rows);
		query.setRows(rows);
		//4.指定默认搜索域。
		query.set("df", "item_keywords");
		//5.设置高亮
		//5.1开启高亮
		query.setHighlight(true);
		//5.2设置高亮字段
		query.addHighlightField("item_title");
		//5.3设置高亮内容
		query.setHighlightSimplePre("<em style=\"color:red\">");
		query.setHighlightSimplePost("</em>");
		//6.调用searchDao,获取SearchResult
		SearchResult searchResult = searchDao.search(query);
		//7.计算总页数,并封装进searchResult
		long recordCount = searchResult.getRecordCount();
		long pageCount = (recordCount + rows-1)/rows;
		searchResult.setPageCount(pageCount);
		//8.返回封装好的searchResult
		return searchResult;
	}

4.4applicationContext-service.xml

dao层包扫描与发布service服务

5.表现层

5.1导入搜索结果静态页面

5.2引入服务

5.3创建controller

请求的url:/search

参数:

1、q 查询条件。

2、page 页码。默认为1

返回值:

逻辑视图,返回值。String。

业务逻辑:

  1. 接收参数
  2. 调用服务查询商品列表
  3. 把查询结果传递给页面。需要参数回显。

在taotao-search-web创建com.taotao.search.controller包,在com.taotao.search.controller创建SearchController

由于搜索是get传参,所以需要编解码成utf-8

package com.taotao.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 com.taotao.common.pojo.SearchResult;
import com.taotao.search.service.SearchService;

@Controller
public class SearchController {
	@Value("${ITEM_ROWS}")
	private Integer ITEM_ROWS;
	@Autowired
	private SearchService searchService;
	/**
	 * 接收q,返回查询结果
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping("/search")
	public String search(@RequestParam("q")String queryString, 
			@RequestParam(defaultValue="1")Integer page, Model model) throws Exception {
		//get请求中文乱码解决
		queryString = new String(queryString.getBytes("ISO-8859-1"),"utf-8");
		
		SearchResult result = searchService.search(queryString, page, ITEM_ROWS);
		//传递给页面
		model.addAttribute("query", queryString);
		model.addAttribute("totalPages", result.getPageCount());
		model.addAttribute("itemList", result.getItemList());
		model.addAttribute("page", page);
		
		//返回逻辑视图
		return "search";
	}
}

5.4配置分页大小

分页大小放入配置文件中

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

<context:property-placeholder location="classpath:resource/resource.properties" />

5.5测试

发现无法翻页。

翻页处理:在taotao-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表达式执行方法,获取第一张图片

猜你喜欢

转载自blog.csdn.net/pdsu161530247/article/details/81974760
今日推荐