B2Ctt商城09 商品详情页面
搜索结果中图片展示不出来,image字段中存储的图片是多张,使用逗号分隔。
修改方法:
publicclassItemInfo extendsTbItem {
public String[] getImages() {
Stringimage= getImage();
if(image != null) {
returnimage.split(",");
}
returnnull;
}
}
页面
<atarget="_blank"href="/item/${item.id }.html">
<img data-lazyload="${item.images[0]}"/>
</a>
1 商品详情页面展示
1.1 需求分析
需要在taotao-portal中调用taotao-rest发布的服务,查询商品详情。
1、商品的基本信息
2、商品的描述
3、商品的规格
当用户请求商品详情页面时,只需要把商品基本信息展示出来,为了快速响应用户。
商品的描述可以延迟加载,延迟一秒钟加载。
商品的规格参数按需加载,当用户点击商品规格参数的标签页此时加载。
1.2 服务发布
需要在taotao-rest工程中发布服务
1、取商品基本信息的服务
2、取商品描述的服务
3、取商品规格的服务
需要把商品信息添加到缓存中。设置商品的过期时间,过期时间为一天。需要缓存同步。
1.1.1.1 Service层
1.1.1.1 添加缓存逻辑
Redis的hash类型中的key是不能设置过期时间。如果还需要对key进行分类可以使用折中的方案。
Key的命名方式:
Itheima:javaee16:01=袁飞
Itheima:javaee16:02=张飞
接收商品id,根据商品id查询商品基本信息。返回一个商品的pojo,使用taotaoResult包装返回。
public classItemServiceImpl implements ItemService {
@Autowired
private TbItemMapperitemMapper;
@Autowired
private TbItemDescMapperitemDescMapper;
@Autowired
private TbItemParamItemMapperitemParamMapper;
@Autowired
private RedisClientMapperredisClientMapper;
#基本信息:
REDIS_ITEM_KEY:REDIS_ITEM_KEY
#缓存有效期 60*60*24
REDIS_ITEM_EXPIRE=86400
@Value("${REDIS_ITEM_KEY}")
private String REDIS_ITEM_KEY;
@Value("${REDIS_ITEM_EXPIRE}")
private IntegerREDIS_ITEM_EXPIRE;
@Override
public TaotaoResultgetItemBaseInfo(longitemId){
String key = REDIS_ITEM_KEY +":" +itemId +":base";
// 加try catch哪怕出现异常也不影响正常逻辑
try {
//添加缓存逻辑
//从缓存中取商品信息,商品id对应的信息
String json = redisClientMapper.get(key);
// 判断是否有值
if(!StringUtils.isBlank(json)){
//把json转换成java对象
TbItemitem= JsonUtils.jsonToPojo(json, TbItem.class);
return TaotaoResult.ok(item);
}
}catch(Exceptione) {
e.printStackTrace();
}
TbItemitem= itemMapper.selectByPrimaryKey(itemId);
try {
//把商品信息写入缓存
redisClientMapper.set(key, JsonUtils.objectToJson(item));
//设置key的有效期
redisClientMapper.expire(key,REDIS_ITEM_EXPIRE);
}catch(Exceptione) {
e.printStackTrace();
}
return TaotaoResult.ok(item);
}
1.1.1.2 Controller层
接收商品id调用Service查询商品信息,返回商品对象,使用TaotaoResult包装。
Url:/rest/item/info/{itemId}
@Controller
@RequestMapping("/item")
public classItemController {
@Autowired
private ItemServiceitemService;
@RequestMapping("/info/{itemId}")
@ResponseBody
public TaotaoResultgetItemBaseInfo(@PathVariable LongitemId){
TaotaoResultresult= itemService.getItemBaseInfo(itemId);
return result;
}
描述 和 规则参数
@RequestMapping("/desc/{itemId}")
@ResponseBody
public TaotaoResultgetItemDescInfo(@PathVariable LongitemId){
TaotaoResultresult= itemService.getItemDescInfo(itemId);
return result;
}
@RequestMapping("/param/{itemId}")
@ResponseBody
public TaotaoResultgetItemParam(@PathVariableLongitemId){
TaotaoResultresult= itemService.getItemParam(itemId);
return result;
}
service
@Override
public TaotaoResultgetItemParam(longitemId) {
Stringkey= REDIS_ITEM_KEY+":"+ itemId+":param";
try {
Stringjson= redisClientMapper.get(key);
// 判断是否有值
if(!StringUtils.isBlank(json)){
TbItemParamItemitemParam= JsonUtils.jsonToPojo(json, TbItemParamItem.class);
return TaotaoResult.ok(itemParam);
}
}catch(Exceptione) {
e.printStackTrace();
}
TbItemParamItemExampleexample=newTbItemParamItemExample();
Criteriacriteria= example.createCriteria();
criteria.andItemIdEqualTo(itemId);
List<TbItemParamItem>list=itemParamMapper.selectByExample(example);
if( list != null && list.size() > 0 ) {
TbItemParamItemitemParam=list.get(0);
try {
//把商品信息写入缓存
redisClientMapper.set(key, JsonUtils.objectToJson(itemParam));
//设置key的有效期
redisClientMapper.expire(key,REDIS_ITEM_EXPIRE);
}catch(Exceptione) {
e.printStackTrace();
}
return TaotaoResult.ok(itemParam);
}
return TaotaoResult.build(400,"无此商品规则");
}
2.1 使用taotao-portal调用服务
1.1.1 需求分析
当用户访问商品详情页面时,需要加载商品基本信息。延迟加载商品描述、按需加载商品的规格参数。
1.1.2 商品基本信息的查询
当商品页面展示时,数据已经到位。
请求的url:/item/{itemId}.html
<a target="_blank" href="/item/${item.id }.html">
<img data-lazyload="${item.images[0]}"/>
</a>
1.1.3 Service层
接收商品id,调用taotao-rest的服务,查询商品的基本信息。得到一个json字符串。需要把json转换成java对象。然后在jsp页面渲染。
#基础url
REST_BASE_URL=http://localhost:8081/rest
#商品基本信息
REST_BASE_ITEM=/item/info/
@Service
public classItemServiceImpl implements ItemService {
@Value("${REST_BASE_URL}")
private StringREST_BASE_URL;
@Value("${REST_BASE_ITEM}")
private StringREST_BASE_ITEM;
@Override
public ItemInfo getItemById(longitemId) {
//调用rest的服务查询商品基本信息
try {
Stringresult= HttpClientUtil.doGet(REST_BASE_URL +REST_BASE_ITEM+ itemId);
if ( !StringUtils.isBlank(result) ) {
TaotaoResulttaotaoResult= TaotaoResult.formatToPojo(result, ItemInfo.class);
if(taotaoResult.getStatus() ==200) {
ItemInfoitem= (ItemInfo)taotaoResult.getData();
returnitem;
}
}
}catch(Exceptione) {
e.printStackTrace();
}
return null;
}
}
1.1.1.3 Controller层
接收页面传递过来的商品id,调用Service查询商品基本信息。传递给jsp页面。返回逻辑视图,展示商品详情页面。
@Controller
public classItemController {
@Autowired
private ItemServiceitemService;
@RequestMapping("/item/{itemId}")
public String showItem(@PathVariable LongitemId, Model model){
ItemInfoitem =itemService.getItemById(itemId);
model.addAttribute("item",item);
return "item";
}
}
* 商品描述延迟加载
jsp页面
<div id="item-desc" class="detail-content">
${itemDesc.itemDesc}
</div>
展示商品介绍
搜索id item-desc 找到对应函数
var itemControl = {
param:{
descUrl:"/item/desc/",
paramUrl:"/item/param/"
},
//请求商品描述
getItemDesc:function(itemId) {
$.get(itemControl.param.descUrl+itemId+".html",function(data){
//返回商品描述的html,直接显示到页面
$("#item-desc").append(data);
});
},
$(function(){
//取商品id
var itemId = "${item.id}";
//延迟一秒加载商品描述信息
setTimeout(function(){
itemControl.getItemDesc(itemId);
},1000);
});
延迟加载请求的URL:/item/desc/{itemId}.html
参数:商品id
返回值:商品描述信息(html片段)
service
接收商品id,调用taotao-rest的服务根据商品id查询商品描述信息。得到json数据。
把json转换成java对象
从java对象中把商品描述取出来。返回商品描述字符串。
参数:商品id
返回值:字符串(商品描述的html片段)
@Override
public StringgetItemDescById(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;
}1.1.1.1 Controller层
接收商品id,调用Service查询商品的描述信息,返回一个字符串,是商品描述的片段。需要使用@ResponseBody。
, produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8") 解决乱码问题
@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; } |
1.1.1 商品规格参数展示
按需加载。当用户点击规格参数tab页时触发一个单击事件,在事件中异步加载规格参数信息。规格参数内容是html片段。返回字符串。
jsp页面保证点击一次会请求,多次点击不会重复请求
//参数请求flag
haveParam:false,
//请求规格参数
getItemParam:function(itemId) {
//如果没有查询过规格参数,就做请求
if(!itemControl.haveParam) {
$.get(itemControl.param.paramUrl+itemId+".html",function(data){
//返回商品规格的html,直接显示到页面
$("#product-detail-2").append(data);
//更改flag状态
itemControl.haveParam= true;
});
}
}
<div id="product-detail-2"> 规则参数 展示位置
${itemParam}
</div>
$(function(){
//取商品id
var itemId = "${item.id}";
//给商品规格参数tab页绑定事件
$("#p-con-attr").bind("click",function(){
itemControl.getItemParam(itemId);
});
tab页点击调用方法
@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;
}@Override
public StringgetItemParam(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("<tablecellpadding=\"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(" <tdclass=\"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 "";
}