简介
taotao-search工程独立于rest,portal,manager工程,通过 http调用 solr服务器提供的索引服务完成对商品的检索。 系统架构。
搭建
<dependency >
<groupId > org.apache.solr</groupId >
<artifactId > solr-solrj</artifactId >
</dependency >
<dependency >
<groupId > org.slf4j</groupId >
<artifactId > slf4j-api</artifactId >
</dependency >
在pom.xml中配置tomcat端口号为8083。 在pom.xml中配置资源路径,将mapper包下的mapper的配置文件导出。
默认路径为 src/main/resources ,配置之后的值覆盖默认值。pom的属性详解 。
<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 >
web.xml都改为search相关名称,url前缀为/search/。 mybatis-config.xml开启驼峰命名转换,用于数据库带 _ 的列名和java变量的驼峰命名转换,注意节点配置的顺序。mybatis核心配置文件的节点说明 。
<configuration >
<settings >
<setting name ="mapUnderscoreToCamelCase" value ="true" />
</settings >
<plugins >
<plugin interceptor ="com.github.pagehelper.PageInterceptor" >
<property name ="helperDialect" value ="mysql" />
</plugin >
</plugins >
</configuration >
solr.properties和spirng-solr.xml配置solr服务器相关属性。
#solrcore的远程地址
SOLR.SERVER.URL=http:
<context:property-placeholder location ="classpath:resource/*.properties" />
<bean id ="solrClient" class ="org.apache.solr.client.solrj.impl.HttpSolrClient" >
<constructor-arg name ="builder" value ="${SOLR.SERVER.URL}" />
</bean >
导入商品数据
需求
导入所有商品信息,包括:id、标题、卖点、价格、图片、类目名称、商品描述。 请求url:/search/manager/importall 请求参数:无 响应参数:TaoTaoResult,包含商品信息列表。
Dao层
商品信息涉及三张表,tb_item,tb_item_cat,tb_item_desc。 在pojo包下创建Item,储存商品信息。
public class Item {
private String id;
private String title;
private String sellPoint;
private long price;
private String image;
private String categoryName;
private String itemDesc;
}
在item下创建ItemMapper接口和映射文件,联结查询商品信息列表。
public interface ItemMapper {
List<Item> getItemList();
}
?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,
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
</select >
</mapper >
Service层
创建ItemService和实现类,从mysql中查询商品信息,并使用solrj将商品按照设置好的域名导入solr服务器的索引库,返回TaoTaoResult。
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private SolrClient solrClient;
@Override
public TaotaoResult importAllItems () {
List<Item> itemList = itemMapper.getItemList();
try {
for (Item item : itemList) {
SolrInputDocument document = new SolrInputDocument();
document.setField("id" , item.getId());
document.setField("item_title" , item.getTitle());
document.setField("item_sell_point" , item.getSellPoint());
document.setField("item_price" , item.getPrice());
document.setField("item_image" , item.getImage());
document.setField("item_category_name" , item.getCategoryName());
document.setField("item_desc" , item.getItemDesc());
solrClient.add(document);
}
solrClient.commit();
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500 , ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok();
}
}
Controller层
创建ItemController,调用service层,将商品信息导入solr索引库,返回TaotaoResult。
@Controller
@RequestMapping ("/manager" )
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping ("/importall" )
@ResponseBody
public TaotaoResult importAllItems () {
TaotaoResult result = itemService.importAllItems();
return result;
}
}
发布搜索服务
需求
提供对外接口,根据查询字符串和分页查询信息,查询商品列表。 请求url:/search/query?q={查询字符串}&page={page}&rows={rows} 请求参数:查询字符串、分页信息page(默认1)和rows(默认60)。 响应参数:TaoTaoResult,包装商品搜索结果。
Dao层
根据SolrQuery查询,返回查询结果。 在pojo下创建SearchResult,包含查询结果,总记录数,总页数,当前页。
public class SearchResult {
private List<?> list;
private long recordCount;
private long pageCount;
private long curPage;
}
在dao下创建SearchDao和实现类,根据SolrQuery查询,将结果转换为Item列表,返回SearchResult。
@Repository
public class SearchDaoImpl implements SearchDao {
@Autowired
private SolrClient solrClient;
@Override
public SearchResult search (SolrQuery query) throws Exception {
SearchResult result = new SearchResult();
QueryResponse queryResponse = solrClient.query(query);
SolrDocumentList solrDocuments = queryResponse.getResults();
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
result.setRecordCount(solrDocuments.getNumFound());
List<Item> itemList = new ArrayList<>();
for (SolrDocument solrDocument : solrDocuments) {
Item item = new Item();
item.setId((String) solrDocument.get("id" ));
List<String> highlightList = highlighting.get(solrDocument.get("id" )).get("item_title" );
String title = "" ;
if (highlightList != null && highlightList.size() > 0 ) {
title = highlightList.get(0 );
} else {
title = (String) solrDocument.get("item_title" );
}
item.setTitle(title);
item.setImage((String) solrDocument.get("item_image" ));
item.setPrice((long ) solrDocument.get("item_price" ));
item.setSellPoint((String) solrDocument.get("item_sell_point" ));
item.setCategoryName((String) solrDocument.get("item_category_name" ));
itemList.add(item);
}
result.setList(itemList);
return result;
}
}
Service层
在service包下创建SearchService和实现类,根据查询字符串、分页信息设置SolrQuery,并设置默认搜索域、高亮文本前后缀,执行查询之后计算总页数,返回SearchResult。
@Service
public class SearchServiceImpl implements SearchService {
@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_keywords" );
query.setHighlight(true );
query.addHighlightField("item_title" );
query.setHighlightSimplePre("<em style=\"color:red\">" );
query.setHighlightSimplePost("</em>" );
SearchResult searchResult = searchDao.search(query);
long recordCount = searchResult.getRecordCount();
long pageCount = recordCount / rows;
if (recordCount % rows > 0 ) {
pageCount++;
}
searchResult.setPageCount(pageCount);
searchResult.setCurPage(page);
return searchResult;
}
}
Controller层
controller包下创建SearchController,根据查询字符串、分页信息查询,返回包装查询结果的TaoTaoResult的json。
@Controller
@RequestMapping
public class SearchController {
@Autowired
private SearchService searchService;
@RequestMapping (value = "/query" , method = RequestMethod.GET)
@ResponseBody
public TaotaoResult search (@RequestParam ("q") String queryString, @RequestParam (defaultValue = "1" ) Integer page,
@RequestParam (defaultValue = "60" ) Integer rows) {
if (StringUtils.isBlank(queryString)) {
return TaotaoResult.build(400 , "查询条件不能为空" );
}
SearchResult searchResult = null ;
try {
searchResult = searchService.search(queryString, page, rows);
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500 , ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok(searchResult);
}
}
运行工程