1. 页面分析 (1) 页面跳转 在首页的顶部,有一个输入框: 当我们输入任何文本,点击搜索,就会跳转到搜索页 search.html 了: 并且将搜索关键字以请求参数携带过来: 我们打开 search.
1.
<script type="text/javascript"> var vm = new Vue({ el: "#searchApp", data: { }, components:{ // 加载页面顶部组件 lyTop: () => import("./js/pages/top.js") } }); </script>
这个Vue实例中,通过import导入的方式,加载了另外一个js:top.js并作为一个局部组件。top其实是页面顶部导航组件,我们暂时不管
(2)发起异步请求
data: {
search:{
key:"", // 搜索页面的关键字
},
goodsList:[]
},
我们通过钩子函数created,在页面加载时获取请求参数,并记录下来。
created(){
// 判断是否有请求参数
if(!location.search){
return;
}
// 将请求参数转为对象
const search = ly.parse(location.search.substring(1));
// 记录在data的search对象中
this.search = search;
// 发起请求,根据条件搜索
this.loadData();
}
在浏览器中进行测试:
然后发起请求,搜索数据。
在leyou-gateway中的CORS配置类中,添加允许信任域名:
并在leyou-gateway工程的Application.yml中添加网关映射:
测试:
2.
-
请求方式:Post
-
请求路径:/search/page,不过前面的/search应该是网关的映射路径,因此真实映射路径page,代表分页查询
-
package lucky.leyou.domain; public class SearchRequest { private String key;// 搜索条件 private Integer page;// 当前页 private static final Integer DEFAULT_SIZE = 20;// 每页大小,不从页面接收,而是固定大小 private static final Integer DEFAULT_PAGE = 1;// 默认页 public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Integer getPage() { if(page == null){ return DEFAULT_PAGE; } // 获取页码时做一些校验,不能小于1 return Math.max(DEFAULT_PAGE, page); } public void setPage(Integer page) { this.page = page; } public Integer getSize() { return DEFAULT_SIZE; } }
返回结果:作为分页结果,一般都两个属性:当前页数据、总条数信息,我们可以使用之前定义的PageResult类
package lucky.leyou.controller; import lucky.leyou.common.domain.PageResult; import lucky.leyou.domain.Goods; import lucky.leyou.domain.SearchRequest; import lucky.leyou.service.SearchService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping public class SearchController { @Autowired private SearchService searchService; /** * 搜索商品 * * @param request * @return */ @PostMapping("page") public ResponseEntity<PageResult<Goods>> search(@RequestBody SearchRequest request) { PageResult<Goods> result = this.searchService.search(request); if (result == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } return ResponseEntity.ok(result); } }
(2)service
@Autowired private GoodsRepository goodsRepository; public PageResult<Goods> search(SearchRequest request) { String key = request.getKey(); // 判断是否有搜索条件,如果没有,直接返回null。不允许搜索全部商品 if (StringUtils.isBlank(key)) { return null; } // 自定义查询构建器,构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 1、对key进行全文检索查询 queryBuilder.withQuery(QueryBuilders.matchQuery("all", key).operator(Operator.AND)); // 2、通过sourceFilter设置返回的结果字段,我们只需要id、skus、subTitle queryBuilder.withSourceFilter(new FetchSourceFilter( new String[]{"id","skus","subTitle"}, null)); // 3、分页 // 准备分页参数 int page = request.getPage(); int size = request.getSize(); queryBuilder.withPageable(PageRequest.of(page - 1, size)); // 4、查询,获取结果 Page<Goods> pageInfo = this.goodsRepository.search(queryBuilder.build()); // 封装结果并返回 return new PageResult<>(pageInfo.getTotalElements(), pageInfo.getTotalPages(), pageInfo.getContent()); }
注意点:我们要设置SourceFilter,来选择要返回的结果,否则返回一堆没用的数据,影响查询效率。
(3)测试
重启search微服务,刷新页面测试:
复制响应结果到: