https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040html
第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第五天】java
第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第六天】ajax
第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第七天】(redis緩存)redis
第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第八天】(solr服務器搭建、搜索功能實現)spring
第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第九天】(商品詳情頁面實現)json
今天的內容:緩存
一、在taotao-portal工程中調用taotao-search工程發佈的服務。實現商品搜索功能。服務器
二、點擊商品的圖片,打開商品詳情頁面app
a) 商品基本信息框架
b) 延遲加載商品詳情。延遲一秒加載使用ajax
c) 商品的規格參數。按需加載,當用戶點擊商品規格參數tab頁,加載ajax。
需求分析
用戶在首頁中輸入查詢條件,點擊查詢向taotao-portal發送請求,參數就是查詢的條件,頁碼。Taoto-portal調用taotao-search發佈的服務進行搜索,參數應該是查詢條件和頁碼及每頁顯示的記錄數(參數可選)。Taotao-search返回一個json格式的數據(TaotaoResult包裝一個SearchResult對象)。Taotao-portal接收json數據須要把json數據轉換成java對象。把java對象傳遞給jsp頁面,jsp渲染java對象獲得商品查詢結果頁面。
接收兩個參數一、查詢條件二、頁碼。調用taotao-search的搜索服務。接收返回的json數據,把json轉換成java對象返回SearchResult對象。
@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 { // 調用服務獲得JSON格式 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(); return result; } } catch (Exception e) { e.printStackTrace(); } // 程序正常執行走try{}代碼塊,必然會return rsult; // 此處的return null;只是爲了這個方法返回值類型檢查不報錯 return null; } }
2.4 Controller層
功能:接收請求的參數查詢條件和頁碼。調用Service查詢商品列表獲得SearchResult對象。
須要把
Query:回顯的查詢條件
totalPages:總頁數
itemList:商品列表
Page:當前頁碼
傳遞到頁面。返回一個邏輯視圖search字符串。
//首頁商品搜索Controller @Controller public class PortalSearchController { @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:
package com.taotao.common.pojo; public class Item { private String id; private String title; private String sell_point; private long price; private String image; private String category_name; private String item_des; public String[] getImages() { if(image != null) { String[] images = image.split(","); return images; } return null; }
須要在taotao-portal中調用taotao-rest發佈的服務,查詢商品詳情。
一、商品的基本信息
二、商品的描述
三、商品的規格
當用戶請求商品詳情頁面時,只須要把商品基本信息展現出來,爲了快速響應用戶。商品的描述能夠延遲加載,延遲一秒鐘加載。商品的規格參數按需加載,當用戶點擊商品規格參數的標籤頁此時再加載。
須要在taotao-rest工程中發佈服務
一、取商品基本信息的服務
二、取商品描述的服務
三、取商品規格的服務
須要把商品信息添加到緩存中。設置商品的過時時間,過時時間爲一天。須要緩存同步。
查詢的表tb_item
接收商品id,根據商品id查詢商品基本信息。返回一個商品的pojo,使用taotaoResult包裝返回。
/** * 商品信息管理Service * * @author kangy * */ @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); } }
接收商品id調用Service查詢商品信息,返回商品對象,使用TaotaoResult包裝。
Url:/rest/item/info/{itemId}
@RestController @RequestMapping("/item") public class ItemController { @Autowired private ItemService itemService; @RequestMapping("/info/{itemId}") public TaotaoResult getItemBaseInfo(@PathVariable Long itemId) { TaotaoResult result = itemService.getItemBaseInfo(itemId); return result; } }
添加緩存邏輯
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 * * @author kangy * */ @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"); // 判斷是否有值 // commons.lang3.StringUtils 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); } }
根據商品id取商品描述信息。單表查詢tb_item_desc。
Dao層
使用逆向工程
Service層
接收商品id根據商品id查詢商品描述。返回商品描述的pojo。使用TaotaoResult包裝。
須要添加緩存邏輯。
@Override public TaotaoResult getItemDesc(long itemId) { // 添加緩存邏輯 try { // 1.從緩存中取商品描述,商品id對應的信息 String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":desc"); // 判斷是否有值 // commons.lang3.StringUtils if (!StringUtils.isBlank(json)) { // 把json轉換成java對象 TbItemDesc itemDesc = JsonUtils.jsonToPojo(json, TbItemDesc.class); return TaotaoResult.ok(itemDesc); } } catch (Exception e) { e.printStackTrace(); } // 2.根據商品id查詢商品描述 TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId); try { // 3.把商品描述寫入緩存 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(); } // 4.使用TaoTaoresult包裝一下 return TaotaoResult.ok(itemDesc); }
須要從tb_item_param_item表中根據商品id取出商品的規格參數信息。返回pojo對象,使用TaotaoResult包裝。
接收商品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(); 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, "無此商品規格"); }
需求分析
當用戶訪問商品詳情頁面時,須要加載商品基本信息。延遲加載商品描述、按需加載商品的規格參數。
當商品頁面展現時,數據已經到位。
請求的url:/item/{itemId}.html
接收商品id,調用taotao-rest的服務,查詢商品的基本信息。獲得一個json字符串。須要把json轉換成java對象。而後在jsp頁面渲染。
@Service public class ItemServiceImpl implements ItemService { @Value("${REST_BASE_URL}") private String REST_BASE_URL; @Value("${ITEM_INFO_URL}") private String ITEM_INFO_URL; @Override public TbItem getItemById(Long itemId) { try { //調用rest的服務查詢商品基本信息 String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_INFO_URL + itemId); if(!StringUtils.isBlank(json)) { TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, ItemInfo.class); //須要判斷並強轉變量類型 if(taotaoResult.getStatus() == 200) { TbItem item = (TbItem) taotaoResult.getData(); return item; } } } catch (Exception e) { e.printStackTrace(); } return null; } }
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:
package com.taotao.portal.pojo; import com.taotao.pojo.TbItem; public class ItemInfo extends TbItem { public String[] getImages() { String image = getImage(); if (image != null) { String[] images = image.split(","); return images; } return null; } }
當商品詳情頁面加載完畢後延遲一秒鐘ajax請求商品詳情。
請求的URL:/item/desc/{itemId}.html
參數:商品id
返回值:商品描述信息(html片斷)
接收商品id,調用taotao-rest的服務根據商品id查詢商品描述信息。獲得json數據。把json轉換成java對象。從java對象中把商品描述取出來。返回商品描述字符串。
參數:商品id
返回值:字符串(商品描述的html片斷)
/** * 取商品描述 */ @Override public String getItemDescById(Long itemId) { try { // 調用rest的服務查詢商品描述基本信息 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(); return result; } } catch (Exception e) { e.printStackTrace();// TODO: handle exception } return null; }
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; }
按需加載。當用戶點擊規格參數tab頁時觸發一個單擊事件,在事件中異步加載規格參數信息。規格參數內容是html片斷。返回字符串。
@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 ""; }
頁面的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); return string; }
請求方法爲post,客戶端提交表單。包含
username //用戶名
password //密碼
phone //手機號
email //郵箱
接收參數調用mapper向user表中添加記錄。返回taotaoResult對象。若是成功200失敗400異常500.
能夠使用逆向工程生成代碼
接收TbUser對象,補全user的屬性。向tb_user表插入記錄。返回taoTaoResult。
@Override public TaotaoResult createUser(TbUser user) { user.setUpdated(new Date()); user.setCreated(new Date()); //spring框架的MD5工具加密 user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes())); userMapper.insert(user); return TaotaoResult.ok(); }
Controller層
//建立用戶的方法 @RequestMapping("/register") public TaotaoResult createUser(TbUser user) { try { TaotaoResult result = userService.createUser(user); return result; } catch (Exception e) { return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e)); } }
==========================================================
參考資料:
end