淘淘商城第九天


1   课程计划

1、solr服务的搭建(单机版)

2、把商品数据导入到索引库中

3、创建一个taotao-search工程,发布搜索服务。

4、实现搜索服务。SolrJ客户端调用solr服务,实现商品搜素。返回json数据。

 

今天的内容:

1、在taotao-portal工程中调用taotao-search工程发布的服务。实现商品搜索功能。

2、点击商品的图片,打开商品详情页面

a)        商品基本信息

b)       延迟加载商品详情。延迟一秒加载使用ajax

c)        商品的规格参数。按需加载,当用户点击商品规格参数tab页,加载ajax。

 

2   商品搜索的实现

 

2.1  需求分析

用户在首页中输入查询条件,点击查询向taotao-portal发送请求,参数就是查询的条件,页码。Taoto-portal调用taotao-search发布的服务进行搜索,参数应该是查询条件和页码及每页显示的记录数(参数可选)。Taotao-search返回一个json格式的数据(TaotaoResult包装一个SearchResult对象)。Taotao-portal接收json数据需要把json数据转换成java对象。把java对象传递给jsp页面,jsp渲染java对象得到商品查询结果页面。

 

请求url:http://localhost:8082/search.html?q=查询条件

参数:q:查询条件

返回结果:商品列表页面(jsp)

Query:回显的查询条件

totalPages:总页数

itemList:商品列表

Page:当前页码

翻页处理:

 

2.2  Dao层

木有

 

2.3  Service层

接收两个参数1、查询条件2、页码。调用taotao-search的搜索服务。接收返回的json数据,把json转换成java对象返回SearchResult对象。

 

从taotao-search中复制SearchResult和Item两个pojo类。

 

@Service

public class SearchServiceImpl implements SearchService {

 

     @Value("${SEARCH_BASE_URL}")

     private String SEARCH_BASE_URL;

    

     @Override

     public SearchResult search(String queryString, int page) {

          // 调用taotao-search的服务

          //查询参数

          Map<String, String> param = new HashMap<>();

          param.put("q", queryString);

          param.put("page", page + "");

          try {

               //调用服务

               String json = HttpClientUtil.doGet(SEARCH_BASE_URL, param);

               //把字符串转换成java对象

               TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, SearchResult.class);

               if (taotaoResult.getStatus() == 200) {

                    SearchResult result = (SearchResult) taotaoResult.getData();

                    returnresult;

               }

              

          } catch (Exception e) {

               e.printStackTrace();

          }

          returnnull;

     }

 

}

 

 

2.4  Controller层

功能:接收请求的参数查询条件和页码。调用Service查询商品列表得到SearchResult对象。

需要把

Query:回显的查询条件

totalPages:总页数

itemList:商品列表

Page:当前页码

传递到页面。返回一个逻辑视图search字符串。

@Controller

public class SearchController {

 

     @Autowired

     private SearchService searchService;

    

     @RequestMapping("/search")

     public String search(@RequestParam("q")String queryString, @RequestParam(defaultValue="1")Integer page, Model model) {

          if (queryString != null) {

               try {

                    queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");

               } catch (UnsupportedEncodingException e) {

                    e.printStackTrace();

               }

          }

          SearchResult searchResult = searchService.search(queryString, page);

          //向页面传递参数

          model.addAttribute("query", queryString);

          model.addAttribute("totalPages", searchResult.getPageCount());

          model.addAttribute("itemList", searchResult.getItemList());

          model.addAttribute("page", page);

         

          return "search";

         

     }

}

 

2.5  存在的问题

搜索结果中图片展示不出来,image字段中存储的图片是多张,使用逗号分隔。

修改方法:

Pojo:

Jsp中:

 

3   商品详情页面展示

3.1  需求分析

需要在taotao-portal中调用taotao-rest发布的服务,查询商品详情。

1、商品的基本信息

2、商品的描述

3、商品的规格

 

当用户请求商品详情页面时,只需要把商品基本信息展示出来,为了快速响应用户。商品的描述可以延迟加载,延迟一秒钟加载。商品的规格参数按需加载,当用户点击商品规格参数的标签页此时加载。

 

3.2  服务发布

需要在taotao-rest工程中发布服务

1、取商品基本信息的服务

2、取商品描述的服务

3、取商品规格的服务

需要把商品信息添加到缓存中。设置商品的过期时间,过期时间为一天。需要缓存同步。

 

3.2.1   取商品基本信息

3.2.1.1        Dao层

查询的表tb_item:

 

3.2.1.2        Service层

接收商品id,根据商品id查询商品基本信息。返回一个商品的pojo,使用taotaoResult包装返回。

@Service

public class ItemServiceImpl implements ItemService {

 

     @Autowired

     private TbItemMapper itemMapper;

     @Override

     public TaotaoResult getItemBaseInfo(long itemId) {

          //根据商品id查询商品信息

          TbItem item = itemMapper.selectByPrimaryKey(itemId);

          //使用TaotaoResult包装一下

         

          return TaotaoResult.ok(item);

     }

 

}

 

3.2.1.3        Controller层

接收商品id调用Service查询商品信息,返回商品对象,使用TaotaoResult包装。

Url:/rest/item/info/{itemId}

@Controller

@RequestMapping("/item")

public class ItemController {

 

     @Autowired

     private ItemService itemService;

    

     @RequestMapping("/info/{itemId}")

     @ResponseBody

     public TaotaoResult getItemBaseInfo(@PathVariable Long itemId) {

          TaotaoResult result = itemService.getItemBaseInfo(itemId);

          returnresult;

     }

    

}

 

3.2.1.4        添加缓存逻辑

Redis的hash类型中的key是不能设置过期时间。如果还需要对key进行分类可以使用折中的方案。

Key的命名方式:

Itheima:javaee16:01=袁飞

Itheima:javaee16:02=张飞

 

商品key的定义:

基本信息:

REDIS_ITEM_KEY:商品id:base=json

描述:

REDIS_ITEM_KEY:商品id:desc=json

规格参数:

REDIS_ITEM_KEY:商品id:param=json

@Service

public class ItemServiceImpl implements ItemService {

 

     @Autowired

     private TbItemMapper itemMapper;

     @Value("${REDIS_ITEM_KEY}")

     private String REDIS_ITEM_KEY;

     @Value("${REDIS_ITEM_EXPIRE}")

     private Integer REDIS_ITEM_EXPIRE;

    

     @Autowired

     private JedisClient jedisClient;

    

     @Override

     public TaotaoResult getItemBaseInfo(long itemId) {

          try {

               //添加缓存逻辑

               //从缓存中取商品信息,商品id对应的信息

               String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":base");

               //判断是否有值

               if (!StringUtils.isBlank(json)) {

                    //json转换成java对象

                    TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);

                    return TaotaoResult.ok(item);

               }

              

          } catch (Exception e) {

               e.printStackTrace();

          }

         

          //根据商品id查询商品信息

          TbItem item = itemMapper.selectByPrimaryKey(itemId);

          //使用TaotaoResult包装一下

          try {

               //把商品信息写入缓存

               jedisClient.set(REDIS_ITEM_KEY + ":" + itemId + ":base", JsonUtils.objectToJson(item));

               //设置key的有效期

               jedisClient.expire(REDIS_ITEM_KEY + ":" + itemId + ":base", REDIS_ITEM_EXPIRE);

          } catch (Exception e) {

               e.printStackTrace();

          }

          return TaotaoResult.ok(item);

     }

 

}

 

3.2.2   取商品描述信息

根据商品id取商品描述信息。单表查询tb_item_desc。

3.2.2.1        Dao层

使用逆向工程

 

3.2.2.2        Service层

接收商品id根据商品id查询商品描述。返回商品描述的pojo。使用TaotaoResult包装。

需要添加缓存逻辑。

 

@Override

     public TaotaoResult getItemDesc(long itemId) {

          //添加缓存

          try {

               //添加缓存逻辑

               //从缓存中取商品信息,商品id对应的信息

               String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":desc");

               //判断是否有值

               if (!StringUtils.isBlank(json)) {

                    //json转换成java对象

                    TbItemDesc itemDesc = JsonUtils.jsonToPojo(json, TbItemDesc.class);

                    return TaotaoResult.ok(itemDesc);

               }

          } catch (Exception e) {

               e.printStackTrace();

          }

          //创建查询条件

          TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);

         

          try {

               //把商品信息写入缓存

               jedisClient.set(REDIS_ITEM_KEY + ":" + itemId + ":desc", JsonUtils.objectToJson(itemDesc));

               //设置key的有效期

               jedisClient.expire(REDIS_ITEM_KEY + ":" + itemId + ":desc", REDIS_ITEM_EXPIRE);

          } catch (Exception e) {

               e.printStackTrace();

          }

         

          return TaotaoResult.ok(itemDesc);

     }

 

3.2.2.3        Controller层

接收商品id参数,调用Service查询商品描述。返回TaotaoResult.

@RequestMapping("/desc/{itemId}")

     @ResponseBody

     public TaotaoResult getItemDesc(@PathVariable Long itemId) {

          TaotaoResult result = itemService.getItemDesc(itemId);

          return result;

     }

 

3.2.3   取商品规格参数

需要从tb_item_param_item表中根据商品id取出商品的规格参数信息。返回pojo对象,使用TaotaoResult包装。

 

3.2.3.1        Dao层

使用逆向工程

 

3.2.3.2        Service层

接收商品id调用mapper查询商品规格参数,返回规格参数pojo使用TaotaoResult包装。

添加缓存逻辑。

@Override

     public TaotaoResult getItemParam(long itemId) {

          //添加缓存

          try {

               //添加缓存逻辑

               //从缓存中取商品信息,商品id对应的信息

               String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":param");

               //判断是否有值

               if (!StringUtils.isBlank(json)) {

                    //json转换成java对象

                    TbItemParamItem paramItem = JsonUtils.jsonToPojo(json, TbItemParamItem.class);

                    return TaotaoResult.ok(paramItem);

               }

          } catch (Exception e) {

               e.printStackTrace();

          }

          //根据商品id查询规格参数

          //设置查询条件

          TbItemParamItemExample example = new TbItemParamItemExample();

          Criteria criteria = example.createCriteria();

          criteria.andItemIdEqualTo(itemId);

          //执行查询

          List<TbItemParamItem> list = itemParamItemMapper.selectByExampleWithBLOBs(example);

          if (list != null && list.size()>0) {

               TbItemParamItem paramItem = list.get(0);

               try {

                    //把商品信息写入缓存

                    jedisClient.set(REDIS_ITEM_KEY + ":" + itemId + ":param", JsonUtils.objectToJson(paramItem));

                    //设置key的有效期

                    jedisClient.expire(REDIS_ITEM_KEY + ":" + itemId + ":param", REDIS_ITEM_EXPIRE);

               } catch (Exception e) {

                    e.printStackTrace();

               }

               return TaotaoResult.ok(paramItem);

          }

          return TaotaoResult.build(400, "无此商品规格");

     }

 

3.2.3.3        Controller层

接收商品id调用Service返回TaotaoResult。

@ResponseBody

     public TaotaoResult getItemDesc(@PathVariable Long itemId) {

          TaotaoResult result = itemService.getItemDesc(itemId);

          return result;

     }

 

3.3  使用taotao-portal调用服务

3.3.1   需求分析

当用户访问商品详情页面时,需要加载商品基本信息。延迟加载商品描述、按需加载商品的规格参数。

 

3.3.2   商品基本信息的查询

当商品页面展示时,数据已经到位。

请求的url:/item/{itemId}.html

3.3.2.1        Dao层

没有

 

3.3.2.2        Service层

接收商品id,调用taotao-rest的服务,查询商品的基本信息。得到一个json字符串。需要把json转换成java对象。然后在jsp页面渲染。

 

@Service

public class ItemServiceImpl implements ItemService {

    

    

     @Value("${REST_BASE_URL}")

     private String REST_BASE_URL;

     @Value("${ITME_INFO_URL}")

     private String ITME_INFO_URL;

 

     @Override

     public TbItem getItemById(Long itemId) {

 

          try {

               //调用rest的服务查询商品基本信息

               String json = HttpClientUtil.doGet(REST_BASE_URL + ITME_INFO_URL + itemId);

               if (!StringUtils.isBlank(json)) {

                    TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItem.class);

                    if (taotaoResult.getStatus() == 200) {

                         TbItem item = (TbItem) taotaoResult.getData();

                         return item;

                    }

               }

          } catch (Exception e) {

               e.printStackTrace();

          }

         

          return null;

     }

 

}

 

3.3.2.3        Controller层

接收页面传递过来的商品id,调用Service查询商品基本信息。传递给jsp页面。返回逻辑视图,展示商品详情页面。

 

@Controller

public class ItemController {

    

     @Autowired

     private ItemService itemService;

 

     @RequestMapping("/item/{itemId}")

     public String showItem(@PathVariable Long itemId, Model model) {

          TbItem item = itemService.getItemById(itemId);

          model.addAttribute("item", item);

         

          return "item";

     }

}

 

商品POJO:

 

public class ItemInfo extends TbItem {

 

     public String[] getImages() {

          String image = getImage();

          if (image != null) {

               String[] images = image.split(",");

               return images;

          }

          return null;

     }

}

 

 

3.3.3   商品描述延迟加载

当商品详情页面加载完毕后延迟一秒钟ajax请求商品详情。

请求的URL:/item/desc/{itemId}.html

参数:商品id

返回值:商品描述信息(html片段)

 

3.3.3.1        Dao层

没有

 

3.3.3.2        Service层

接收商品id,调用taotao-rest的服务根据商品id查询商品描述信息。得到json数据。把json转换成java对象从java对象中把商品描述取出来。返回商品描述字符串。

参数:商品id

返回值:字符串(商品描述的html片段)

 

/**

      *   取商品描述

      * <p>Title: getItemDescById</p>

      * <p>Description: </p>

      * @param itemId

      * @return

      * @see com.taotao.portal.service.ItemService#getItemDescById(java.lang.Long)

      */

     @Override

     public String getItemDescById(Long itemId) {

          try {

               //查询商品描述

               String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_DESC_URL + itemId);

               //转换成java对象

               TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItemDesc.class);

               if (taotaoResult.getStatus() == 200) {

                    TbItemDesc itemDesc = (TbItemDesc) taotaoResult.getData();

                    //取商品描述信息

                    String result = itemDesc.getItemDesc();

                    returnresult;

               }

          } catch (Exception e) {

               e.printStackTrace();

          }

          returnnull;

     }

 

3.3.3.3        Controller层

接收商品id,调用Service查询商品的描述信息,返回一个字符串,是商品描述的片段。需要使用@ResponseBody。

@RequestMapping(value="/item/desc/{itemId}", produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")

     @ResponseBody

     public String getItemDesc(@PathVariable Long itemId) {

          String string = itemService.getItemDescById(itemId);

          return string;

     }

 

3.3.4   商品规格参数展示

按需加载。当用户点击规格参数tab页时触发一个单击事件,在事件中异步加载规格参数信息。规格参数内容是html片段。返回字符串。

 

3.3.4.1        Dao层

没有

3.3.4.2        Service层

接收商品id,根据商品id查询规格参数的数据,调用服务端的方法,返回json数据。把json转换成java对象,根据java对象生成html片段,返回。

 

参数:商品id

返回值:字符串(规格参数html)

/**

      * 根据商品id查询规格参数

      * <p>Title: getItemParam</p>

      * <p>Description: </p>

      * @param itemId

      * @return

      * @see com.taotao.portal.service.ItemService#getItemParam(java.lang.Long)

      */

     @Override

     public String getItemParam(Long itemId) {

          try {

               String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_PARAM_URL + itemId);

               //json转换成java对象

               TaotaoResult taotaoResult = TaotaoResult.formatToList(json, TbItemParamItem.class);

               if (taotaoResult.getStatus() == 200) {

                    TbItemParamItem itemParamItem = (TbItemParamItem) taotaoResult.getData();

                    String paramData = itemParamItem.getParamData();

                    //生成html

                    // 把规格参数json数据转换成java对象

                    List<Map> jsonList = JsonUtils.jsonToList(paramData, Map.class);

                    StringBuffer sb = new StringBuffer();

                    sb.append("<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"0\" class=\"Ptable\">\n");

                    sb.append("    <tbody>\n");

                    for(Map m1:jsonList) {

                         sb.append("        <tr>\n");

                         sb.append("            <th class=\"tdTitle\" colspan=\"2\">"+m1.get("group")+"</th>\n");

                         sb.append("        </tr>\n");

                         List<Map> list2 = (List<Map>) m1.get("params");

                         for(Map m2:list2) {

                              sb.append("        <tr>\n");

                              sb.append("            <td class=\"tdTitle\">"+m2.get("k")+"</td>\n");

                              sb.append("            <td>"+m2.get("v")+"</td>\n");

                              sb.append("        </tr>\n");

                         }

                    }

                    sb.append("    </tbody>\n");

                    sb.append("</table>");

                    //返回html片段

                    return sb.toString();

               }

                     

              

          } catch (Exception e) {

               e.printStackTrace();

          }

         

          return "";

     }

 

3.3.4.3        Controller层

页面的ajax请求Controller,请求的url://item/param/{itemId}.html

响应一个字符串。规格参数的片段。@ResponseBody。

 

@RequestMapping(value="/item/param/{itemId}", produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")

     @ResponseBody

     public String getItemParam(@PathVariable Long itemId) {

          String string = itemService.getItemParam(itemId);

          returnstring;

     }

 

3.3.4.4        Jsp

响应规格参数标签页的点击事件,在事件中进行ajax请求规格参数。只需要请求一次即可。

给tab页dom节点绑定单击事件:

请求规格参数的方法:

绑定单击事件:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值