设为首页 收藏本站
查看: 1283|回复: 0

[经验分享] 商城项目(八)

[复制链接]

尚未签到

发表于 2017-12-20 14:39:07 | 显示全部楼层 |阅读模式
搜索系统搭建
  搜索功能需要发布服务共pc端、移动端使用。根据关键词搜索,得到json格式的搜索结果。
  
创建一个搜索系统,发布搜索服务。

系统架构


创建搜索系统
  参考taotao-rest创建。

框架整合

Solr服务的搭建

CentOS单机版安装


  • 第一步:安装jdk、安装tomcat
  • 第二步:解压solr压缩包。
  • 第三步:把dist/solr-4.10.3.war部署到tomcat下。
  •   第四步:解压缩war包。启动tomcat解压。
      

    tail -f logs/catalina.out 看日志
  • 第五步:需要把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包添加到solr工程中。
  • 第六步:创建solrhome。把/root/solr-4.10.3/example/solr文件夹复制一份作为solrhome。
  •   第七步:告诉solr服务solrhome的位置。需要修改web.xml

  

<env-entry>  <env-entry-name>solr/home</env-entry-name>
  <env-entry-value>/usr/local/solr/solrhome</env-entry-value>
  <env-entry-type>java.lang.String</env-entry-type>
  
</env-entry>
  

  


  • 第八步:启动tomcat。
  

./startup.sh  



配置中文分析器、自定义业务域
  分析器使用IKAnalyzer。
  
使用方法:


  • 第一步:把IKAnalyzer依赖的jar包添加到solr工程中。把分析器使用的扩展词典添加到classpath中。
  

cp .jar /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib  

cp ext_stopword.dic IKAnalyzer.cfg.xml mydict.dic /usr/local/solr/tomcat/webapps/solr/WEB-INF/classes  



  • 第二步:需要自定义一个FieldType。/usr/local/solr/solrhome/collection1/conf/Schema.xml中定义。可以在FieldType中指定中文分析器。
  

<fieldType name="text_ik">  <analyzer/>
  
</fieldType>
  

  


  • 第三步:自定义域。指定域的类型为自定义的FieldType。
  Sql语句:
  

SELECT  a.id,
  a.title,
  a.sell_point,
  a.price,
  a.image,
  b.`name` category_name,
  c.item_desc
  
FROM
  tb_item a
  
LEFT JOIN tb_item_cat b ON a.cid = b.id
  
LEFT JOIN tb_item_desc c ON a.id = c.item_id
  
WHERE
  a.`status` = 1
  

  加入/usr/local/solr/solrhome/collection1/conf/Schema.xml中
  

<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
索引库中导入数据
  dataimport插件

Solrj的使用
  测试类
  

public>
  @Test
  public void testSolrJ() throws Exception {
  // 创建连接
  SolrServer solrServer = new HttpSolrServer("http://192.168.204.132:8080/solr");
  // 创建一个文档对象
  SolrInputDocument document = new SolrInputDocument();
  document.addField("id", "solrtest01");
  document.addField("item_title", "测试商品");
  document.addField("item_sell_point", "卖点");
  // 添加到索引库
  solrServer.add(document);
  // 提交
  solrServer.commit();
  }
  

  @Test
  public void testQuery() throws Exception {
  // 创建连接
  SolrServer solrServer = new HttpSolrServer("http://192.168.204.132:8080/solr");
  // 创建一个查询对象
  SolrQuery solrQuery = new SolrQuery();
  solrQuery.setQuery("*:*");
  // 执行查询
  QueryResponse queryResponse = solrServer.query(solrQuery);
  // 取查询结果
  SolrDocumentList solrDocumentList = queryResponse.getResults();
  for (SolrDocument solrDocument : solrDocumentList) {
  System.out.println(solrDocument.get("id"));
  System.out.println(solrDocument.get("item_title"));
  System.out.println(solrDocument.get("item_sell_point"));
  }
  }
  
}
  

导入数据

清除原来的数据


分析
  从数据库中根据sql语句查询数据,遍历数据创建文档对象,把文档对象写入索引库。

Dao层
  Sql语句:
  

SELECT  a.id,
  a.title,
  a.sell_point,
  a.price,
  a.image,
  b.`name` category_name,
  c.item_desc
  
FROM
  tb_item a
  
LEFT JOIN tb_item_cat b ON a.cid = b.id
  
LEFT JOIN tb_item_desc c ON a.id = c.item_id
  
WHERE
  a.`status` = 1
  

  创建一个Mapper文件
  

public interface ItemMapper {  

  List<SearchItem> getItemList();
  
}
  

  

<mapper namespace="com.taotao.search.mapper.ItemMapper" >  <select resultType="com.taotao.search.pojo.SearchItem">
  SELECT
  a.id,
  a.title,
  a.sell_point,
  a.price,
  a.image,
  b.`name` category_name,
  c.item_desc
  FROM
  tb_item a
  LEFT JOIN tb_item_cat b ON a.cid = b.id
  LEFT JOIN tb_item_desc c ON a.id = c.item_id
  WHERE
  a.`status` = 1
  </select>
  
</mapper>
  

<bean>  <property name="basePackage" value="com.taotao.mapper, com.taotao.search.mapper" />
  
</bean>
  

Service层
  取商品列表,遍历列表,创建文档对象,把文档对象写入索引库。
  
要操作索引库需要SolrServer对象,可以把SolrServer放到spring容器中,注入到Service。
  

<!--单机版solr客户端-->  
<bean>
  <constructor-arg name="baseURL" value="http://192.168.204.132:8080/solr"></constructor-arg>
  
</bean>
  

@Service
  
public>  

  @Autowired
  private SolrServer solrServer;
  @Autowired
  private ItemMapper itemMapper;
  

  @Override
  public TaotaoResult importItems() throws Exception {
  // 查询数据库获取商品列表
  List<SearchItem> searchItems = itemMapper.getItemList();
  // 遍历列表
  for (SearchItem item : searchItems) {
  // 创建文档对象
  SolrInputDocument document = new SolrInputDocument();
  document.addField("id", item.getId());
  document.addField("item_title", item.getTitle());
  document.addField("item_sell_point", item.getSell_point());
  document.addField("item_price", item.getPrice());
  document.addField("item_image", item.getImage());
  document.addField("item_category_name", item.getCategory_name());
  document.addField("item_desc", item.getItem_desc());
  // 写入索引库
  solrServer.add(document);
  }
  // 提交
  solrServer.commit();
  return TaotaoResult.ok();
  }
  
}
  

Controller层
  请求一个url,返回TaotaoResult。
  

@Controller  
public>  

  @Autowired
  private ItemService itemService;
  

  @RequestMapping("/importall")
  @ResponseBody
  public TaotaoResult importAll() {
  try {
  TaotaoResult result = itemService.importItems();
  return result;
  } catch (Exception e) {
  e.printStackTrace();
  return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
  }
  }
  
}
  

  pom.xml
  

<build>  <resources>
  <resource>
  <directory>src/main/java</directory>
  <includes>
  <include>**/*.properties</include>
  <include>**/*.xml</include>
  </includes>
  <filtering>false</filtering>
  </resource>
  <resource>
  <directory>src/main/resources</directory>
  <includes>
  <include>**/*.properties</include>
  <include>**/*.xml</include>
  </includes>
  <filtering>false</filtering>
  </resource>
  </resources>
  </build>
  



搜索系统的实现

搜索服务发布
  调用服务传递过来一个查询条件,根据查询条件进行查询。返回查询结果。参数中包括分页条件。
  
参数:


  • String queryString
  • Int page
  •   Int rows

  • 返回结果:返回json数据。
  • 包含查询结果的列表。使用商品的pojo来描述。SearchItem
  • 包含查询结果总记录数。
  • 包含查询结果的总页数。
  • 包含当前页码。
  • 包含查询的状态。
  •   包含错误信息。

  创建一个SearchResult
  
包含四个属性:


  • 1、商品列表
  • 2、查询结果总记录数
  • 3、查询结果的总页数
  • 4、当前页码
  

public>

  private List<SearchItem> itemList;
  private Long recordCount;
  private int pageCount;
  private int curPage;
  

  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 int getPageCount() {
  return pageCount;
  }
  

  public void setPageCount(int pageCount) {
  this.pageCount = pageCount;
  }
  

  public int getCurPage() {
  return curPage;
  }
  

  public void setCurPage(int curPage) {
  this.curPage = curPage;
  }
  
}
  

Dao层
  根据查询条件进行查询,返回查询结果。


  • 参数:SolrQuery对象  
    返回结果:

  • 1、查询结果的商品列表
  • 2、查询结果的总记录数  
    返回SearchResult

  

@Service
  
public>  

  @Autowired
  private SolrServer solrServer;
  

  @Override
  public SearchResult search(SolrQuery query) throws Exception {
  // 执行查询
  QueryResponse response = solrServer.query(query);
  // 取查询结果列表
  SolrDocumentList solrDocumentList = response.getResults();
  List<SearchItem> itemList = new ArrayList<>();
  for (SolrDocument solrDocument : solrDocumentList) {
  // 创建一个SearchItem对象
  SearchItem item = new SearchItem();
  item.setCategory_name((String) solrDocument.get("item_category_name"));
  item.setId((String) solrDocument.get("id"));
  item.setImage((String) solrDocument.get("item_image"));
  item.setPrice((Long) solrDocument.get("item_price"));
  item.setSell_point((String) solrDocument.get("item_sell_point"));
  //取高亮显示
  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 = (String) solrDocument.get("item_title");
  }
  item.setTitle(itemTitle);
  //添加到列表
  itemList.add(item);
  }
  SearchResult result = new SearchResult();
  result.setItemList(itemList);
  //查询结果总数量
  result.setRecordCount(solrDocumentList.getNumFound());
  return result;
  }
  
}
  

Service层
  1、接收查询条件、分页条件。
  
2、创建SolrQuery对象,设置查询条件、分页条件。
  
3、调用dao进行搜索
  
4、计算总页数,把总页数设置到SearchResult对象中,设置当前页属性。
  
5、返回SearchResult
  参数:
  
1、查询条件
  
2、Page
  
3、Rows
  返回结果:
  
SearchResult
  

@Service
  
public>  

  @Autowired
  private SearchDao searchDao;
  

  @Override
  public SearchResult search(String queryString, int page, int rows) throws Exception {
  //创建查询条件
  SolrQuery query = new SolrQuery();
  //设置查询条件
  query.setQuery(queryString);
  //设置分页条件
  query.setStart((page-1)*rows);
  query.setRows(rows);
  //设置默认搜索域
  query.set("df", "item_title");
  //设置高亮
  query.setHighlight(true);
  query.addHighlightField("item_title");

  query.setHighlightSimplePre("<font>  query.setHighlightSimplePost("</font>");
  //执行查询
  SearchResult searchResult = searchDao.search(query);
  //计算总页数
  Long recordCount = searchResult.getRecordCount();
  int pageCount = (int) (recordCount / rows);
  if (recordCount % rows > 0) {
  pageCount++;
  }
  searchResult.setPageCount(pageCount);
  searchResult.setCurPage(page);
  return searchResult;
  }
  
}
  

Controller层
  发布服务。
  
搜索服务的url:/search/q?keyword=xxx&page=1&rows=30
  
参数keyword、page、rows
  
返回结果:json数据,使用TaotaoResult包装SearchResult。
  

@Controller
  
public>  

  @Autowired
  private SearchService searchService;
  

  @RequestMapping("/q")
  @ResponseBody
  public TaotaoResult search(@RequestParam(defaultValue="")String keyword,
  @RequestParam(defaultValue="1")Integer page,
  @RequestParam(defaultValue="30")Integer rows) {
  

  try {
  //转换字符集
  keyword = new String(keyword.getBytes("iso8859-1"), "utf-8");
  SearchResult searchResult = searchService.search(keyword, page, rows);
  return TaotaoResult.ok(searchResult);
  } catch (Exception e) {
  e.printStackTrace();
  return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
  }
  }
  

  
}
  

  http://localhost:8093/search/q?keyword=%E6%89%8B%E6%9C%BA&page=1&rows=10
  


在portal中实现搜索

分析
  调用taotao-search发布的服务,实现搜索。使用HttpClient调用服务。返回json数据。需要把json转换成java对象。把java对象传递给页面。
  请求的url:http://localhost:8082/search.html
  
参数:q:查询条件
  
返回结果:jsp页面(search.jsp)
  Search.jsp分析:
  
数据:
  
Query:查询条件
  
totalPages:总页数
  
itemList:商品列表(每个元素可以是SearchItem)
  
Page:当前页

Service层
  参数:查询条件、page、rows。
  
根据查询调用taotao-search发布的服务,查询商品列表。得到json数据,需要把json转换成java对象,返回SearchResult。
  

@Service
  
public>  

  @Value("${SEARCH_BASE_URL}")
  private String SEARCH_BASE_URL;
  

  @Override
  public SearchResult search(String keyword, int page, int rows) {
  // 调用服务查询商品列表
  Map<String, String> param = new HashMap<>();
  param.put("keyword", keyword);
  param.put("page", page + "");
  param.put("rows", rows + "");
  // 调用服务
  String json = HttpClientUtil.doGet(SEARCH_BASE_URL, param);
  // 转换成java对象
  TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, SearchResult.class);
  // 取返回结果
  SearchResult searchResult = (SearchResult) taotaoResult.getData();
  return searchResult;
  }
  
}
  

Controller层
  接收三个参数:查询条件、page、rows
  
调用服务查询商品列表。
  
把商品列表传递给jsp、参数回显。
  
返回逻辑视图(search.jsp)
  
请求的url:/search
  

@Controller
  
public>  

  @Autowired
  private SearchService searchService;
  

  @RequestMapping("/search")
  public String search(@RequestParam("q") String keyword,
  @RequestParam(defaultValue = "1") Integer page,
  @RequestParam(defaultValue = "60") Integer rows, Model model) {
  // get乱码处理
  try {
  keyword = new String(keyword.getBytes("iso8859-1"), "utf-8");
  } catch (UnsupportedEncodingException e) {
  keyword = "";
  e.printStackTrace();
  }
  SearchResult searchResult = searchService.search(keyword, page, rows);
  // 参数传递给页面
  model.addAttribute("query", keyword);
  model.addAttribute("totalPages", searchResult.getPageCount());
  model.addAttribute("itemList", searchResult.getItemList());
  model.addAttribute("page", searchResult.getCurPage());
  // 返回逻辑视图
  return "search";
  }
  
}
  

  解决图片显示不出来的问题:
  

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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-426067-1-1.html 上篇帖子: 第一篇:编程思路整理 下篇帖子: 淘淘商城部署文档
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表