一、京东和淘宝都一样,每一个搜索都是一次独立的get请求,都是一个独立的URL请求:
既不用post请求,也不用异步,为什么这样做?
1、方便分享好友。
2、get请求是同步请求,可以大幅度为服务器争取缓冲时间,减少服务器压力。异步恰恰相反!!!
二、理解URL请求、面包屑、属性值列表中的每一个get请求:
(1)当前请求url中所包含的属性=面包屑中所包含的属性
(2)在面包屑请求中的属性值,在属性列表都被剔除了
当我点击15.0英寸-15.9英寸,属性列表就变成这样了:
由此可以得出结论:
当点击面包屑去除属性值产生新get请求=url当前请求的属性值-被点击面包屑的属性值
当点击属性值列表产生新的get请求=url当前请求的属性值+被点击的属性值
无论点击面包屑还是属性值,都是一个新的get请求!注意理解这句话。
三、面包屑请求的拼接:
当点击属性值列表产生新的get请求=url当前请求的属性值+被点击的属性值
String urlParam = geturlParam(pmsSearchParam); //拼接URL地址后的属性值字符串
modelMap.put("urlParam",urlParam); //把URL地址传递给前端的每一个属性值,每点击一个属性值,就是一条新的链接
private String geturlParam(PmsSearchParam pmsSearchParam) {
String keyword = pmsSearchParam.getKeyword();
String catalog3Id = pmsSearchParam.getCatalog3Id();
String[] pmsSkuAttrValues = pmsSearchParam.getValueId();
String urlParam = ""; //默认为空
if(StringUtils.isNotBlank(keyword)){
if (StringUtils.isNotBlank(urlParam)){ //如果URL地址问号?后有三级分类id或者搜索关键字,则不为空,才加符号&
urlParam = urlParam + "&";
}
urlParam = urlParam + "keyword=" + keyword;
}
if (StringUtils.isNotBlank(catalog3Id)){
if (StringUtils.isNotBlank(urlParam)){ //如果URL地址问号?后有三级分类id或者搜索关键字,则不为空,才加符号&
urlParam = urlParam + "&";
}
urlParam = urlParam + "catalog3Id=" + catalog3Id;
}
if (pmsSkuAttrValues != null){ 这URL地址问号?后必有三级分类id或者搜索关键字,必不为空,直接在后加符号&,加属性值
for (String pmsSkuAttrValue : pmsSkuAttrValues) {
urlParam = urlParam + "&valueId=" + pmsSkuAttrValue;
}
}
return urlParam;
}
修改了一个重大bug:
这里的名称和es数据库的集合的字段不对应造成的!!!
先前写的直接是字段,而es中是集合里的字段!!!固然查询不到,重大的bug!!!
四、正常查询出来的商品,用户点击商品属性值之后,把该属性值的整组属性删除,模仿京东!!!使用迭代器!!!
(1)分析:如果直接使用for循环,删除列表的数据,列表的索引会重新组合。这种删除方式效率极低,而且还会发生溢界。循环到第1个位置,把他删掉,数组就会重新创建索引,变成0和1,但是你for循环3次,直接就报溢界错误!
(2)用链表删除,也不可取。
(3)使用迭代器iterator最适合,它的特点是游标。它不是集合本身,它是指向集合中某一个元素!!!最适合用来做检查式删除!!!
//用户点击一个属性值,把该属性删掉!模仿京东!使用迭代器!!!
if(pmsSearchParam.getValueId() != null) { //前提条件:用户点击了属性值,才作以下删除操作
String[] delValueIds = pmsSearchParam.getValueId(); //用户选择的属性值
Iterator<PmsBaseAttrInfo> iterator = pmsBaseAttrInfos.iterator(); //从数据库查询到的属性和属性值列表,制作成迭代器!!!
while (iterator.hasNext()) { //迭代器不停的指向下一个元素,有值就返回true继续循环;没有值就返回false跳出循环
PmsBaseAttrInfo pmsBaseAttrInfo = iterator.next(); //迭代器指向下一个属性元素对象
List<PmsBaseAttrValue> attrValueList = pmsBaseAttrInfo.getAttrValueList(); //获取该属性对象的属性值列表
for (PmsBaseAttrValue attrValue : attrValueList) { //循环平台属性值
String attrValueId = attrValue.getId();
for (String delValueId : delValueIds) { //循环用户选择的属性值
if (delValueId.equals(attrValueId)) {
iterator.remove(); //如果平台属性值=用户选择的属性值,则使用迭代器指向的该元素对象移除!!!
}
}
}
}
}
五、到现在属性值列表功能已经做完了,在URL链接中往上加。
现在来完成面包屑功能,可以点击面包屑,去掉该属性值,在URL中去掉该属性值,产生新的URL请求,模仿京东。
用户点击属性值的时候,删除该属性组,同时生成用户点击的属性值为面包屑(难点!!!)
(1)先创建一个面包屑实体类,封装数据传递给前端的
public class pmsSearchCrumb {
private String valueId;
private String valueName;
private String urlParam;
(2)使用迭代器删除属性组的同时,制作面包屑(难点!!!),看注解,并认真理解:
//根据前端接收的关键字、三级分类id、属性值列表去es执行查询,并返回给前端
List<PmsSearchSkuInfo> pmsSearchSkuInfos = searchService.list(pmsSearchParam);
modelMap.put("skuLsInfoList",pmsSearchSkuInfos);
//使用set(集)去重,new一个HashSet列表
HashSet<String> hashSet = new HashSet<>();
for (PmsSearchSkuInfo pmsSearchSkuInfo : pmsSearchSkuInfos) {
List<PmsSkuAttrValue> skuAttrValueList = pmsSearchSkuInfo.getSkuAttrValueList();
for (PmsSkuAttrValue pmsSkuAttrValue : skuAttrValueList) {
//遍历所查询到的商品的属性值id
String valueId = pmsSkuAttrValue.getValueId();
//把每一个属性值id都add进set(集)里,自动去重,重复的全部去掉,这一行代码解决所有问题啊,牛皮!!!
hashSet.add(valueId);
}
}
//既然拿到了去重的属性值id,现在去操作数据 查询 平台属性和属性值
List<PmsBaseAttrInfo> pmsBaseAttrInfos = attrService.getBaseInfoAndValueList(hashSet);
modelMap.put("attrList",pmsBaseAttrInfos);
//用户点击一个属性值,把该属性删掉,使用迭代器!!!同时制作面包屑:属性值id、属性值名称、去掉该属性值后的新URL地址
List<pmsSearchCrumb> pmsSearchCrumbs = new ArrayList<>(); //创建面包屑列表
if(pmsSearchParam.getValueId() != null) { //前提条件:用户点击了属性值,才作以下删除操作
String[] delValueIds = pmsSearchParam.getValueId(); //用户选择的属性值
for (String delValueId : delValueIds) { //循环用户选择的属性值,选择多少个,就有多少个面包屑
pmsSearchCrumb pmsSearchCrumb = new pmsSearchCrumb(); //创建一个新的面包屑对象
pmsSearchCrumb.setValueId(delValueId); //设置属性值id
pmsSearchCrumb.setUrlParam(geturlParamForCrumbs(pmsSearchParam,delValueId));// 设置每个面包屑的URL地址
Iterator<PmsBaseAttrInfo> iterator = pmsBaseAttrInfos.iterator(); //从数据库查询到的属性和属性值列表,制作成迭代器!!!
while (iterator.hasNext()) { //迭代器不停的指向下一个元素,有值就返回true继续循环;没有值就返回false跳出循环
PmsBaseAttrInfo pmsBaseAttrInfo = iterator.next(); //迭代器指向下一个属性元素对象
List<PmsBaseAttrValue> attrValueList = pmsBaseAttrInfo.getAttrValueList(); //获取该属性对象的属性值列表
for (PmsBaseAttrValue attrValue : attrValueList) { //循环平台属性值
String attrValueId = attrValue.getId();
if (delValueId.equals(attrValueId)) {
pmsSearchCrumb.setValueName(attrValue.getValueName()); //重点!!!设置面包屑名称
iterator.remove(); //如果平台属性值=用户选择的属性值,则使用迭代器指向的该元素对象移除!!!
}
}
}
pmsSearchCrumbs.add(pmsSearchCrumb); //把一个 面包屑对象 添加进 面包屑列表
}
}
modelMap.put("attrValueSelectedList",pmsSearchCrumbs);
//用户点击一个属性值,产生一个新的URL地址,拼接URL请求
String urlParam = geturlParam(pmsSearchParam); //拼接URL地址后的属性值字符串
modelMap.put("urlParam",urlParam); //把URL地址传递给前端的每一个属性值,每点击一个属性值,就是一条新的链接
}
//点击面包屑,被点击的属性值id需要去除,即去除URL地址的属性值id,产生新的拼接URL地址
private String geturlParamForCrumbs(PmsSearchParam pmsSearchParam, String delValueId) {
String keyword = pmsSearchParam.getKeyword();
String catalog3Id = pmsSearchParam.getCatalog3Id();
String[] pmsSkuAttrValues = pmsSearchParam.getValueId();
String urlParam = ""; //默认为空
if(StringUtils.isNotBlank(keyword)){
if (StringUtils.isNotBlank(urlParam)){ //如果URL地址问号?后有三级分类id或者搜索关键字,则不为空,才加符号&
urlParam = urlParam + "&";
}
urlParam = urlParam + "keyword=" + keyword;
}
if (StringUtils.isNotBlank(catalog3Id)){
if (StringUtils.isNotBlank(urlParam)){ //如果URL地址问号?后有三级分类id或者搜索关键字,则不为空,才加符号&
urlParam = urlParam + "&";
}
urlParam = urlParam + "catalog3Id=" + catalog3Id;
}
if (pmsSkuAttrValues != null){ //这URL地址问号?后必有三级分类id或者搜索关键字,必不为空,直接在后加符号&和加属性值id
for (String pmsSkuAttrValue : pmsSkuAttrValues) {
if(!pmsSkuAttrValue.equals(delValueId)){ //用户所有点击的属性值,和用户准备要点击的某个属性值,即要去掉该属性值。
urlParam = urlParam + "&valueId=" + pmsSkuAttrValue; //用户准备要点击的某个属性值和所有被点击的属性值匹配,如果不相等,就拼接;如果相等,则不拼接,即去除该面包屑。这样就达到了去除面包屑后的新的URL地址
}
}
}
return urlParam;
}