在开发电商项目时,我们需要实现一个最基本的功能:点击商品的图片,打开商品详情页面。其中,商品页面分为三大部分:
a) 商品基本信息
b) 延迟加载商品详情。延迟一秒加载使用ajax
c) 商品的规格参数。按需加载,当用户点击商品规格参数tab页,加载ajax。
1、Taotao-portal接收页面请求,接收到商品id。
2、调用taotao-rest提供的商品详情的服务,把商品id作为参数传递给服务。接收到商品详细详细。
3、渲染结果,展示商品详细页面
4、为了提高响应速度,商品详情页的内容需要分步骤加载。
第一步:先展示商品基本信息,例如商品的名称、图片、价格。
第二步:展示商品的描述,此时商品页面已经展示完毕,需要ajax请求商品描述。展示的时机是页面加载完毕后一秒钟。
第三步:展示商品规格。当用户点击商品规格选项卡时展示。使用ajax请求商品规格。
5、在搜索页面点击商品的图片或者商品名称请求商品详情页面。
商品详情页请求的url:/item/{itemId}.html
商品描述请求的url:/item/desc/{itemId}.html
商品规格请求的url:/item/param/{itemId}.html
需要在taotao-rest工程中发布服务
1、取商品基本信息的服务
2、取商品描述的服务
3、取商品规格的服务
由于商品详情也是客户经常访问的,需要把商品信息添加到缓存中。Redis是内存数据库也属于稀缺资源,所以不应该永久占用,所以要设置过期时间。过期时间为一天。需要缓存同步。
Redis的hash类型中的key是不能设置过期时间。如果还需要对key进行分类可以使用折中的方案。
Key的命名方式:XXXX:xxxx:~~~~
这样存放在redis中,当我们用可视化客户端时就会以文件夹形式存储
因此,在配置文件resource.properties添加url
#商品基本信息url
ITEM_INFO_URL=/item/info/
#商品描述url
ITEM_DESC_URL=/item/desc/
#商品规格参数url
ITEM_PARAM_URL=/item/param/
因为都是单表查询所以使用逆向工程生成的mapper文件即可。
tb_item
tb_item_desc
tb_item_param_item
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private TbItemMapper itemMapper;
@Autowired
private TbItemDescMapper itemDescMapper;
@Autowired
private TbItemParamItemMapper itemParamItemMapper;
@Value("${REDIS_ITEM_KEY}")
private String REDIS_ITEM_KEY;
@Value("${REDIS_ITEM_EXPIRE}")
private Integer REDIS_ITEM_EXPIRE;
@Autowired
private JedisClientSingle jedisClientSingle;
@Override
public TaotaoResult getItemBaseInfo(long itemId) {
//添加缓存逻辑
try {
//从缓存中取商品信息,商品id对应的信息
String json = jedisClientSingle.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);
//把商品信息写入缓存
try {
jedisClientSingle.set(REDIS_ITEM_KEY+":"+itemId+":base", JsonUtils.objectToJson(item));
//设置key的有效期
jedisClientSingle.expire(REDIS_ITEM_KEY+":"+itemId+":base", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok(item);
}
@Override
public TaotaoResult getItemDesc(long itemId) {
//添加缓存
try {
//添加缓存逻辑
//从缓存中取商品信息,商品id对应的信息
String json = jedisClientSingle.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 {
//把商品信息写入缓存
jedisClientSingle.set(REDIS_ITEM_KEY + ":" + itemId + ":desc", JsonUtils.objectToJson(itemDesc));
//设置key的有效期
jedisClientSingle.expire(REDIS_ITEM_KEY + ":" + itemId + ":desc", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok(itemDesc);
}
@Override
public TaotaoResult getItemParam(long itemId) {
//添加缓存
try {
//添加缓存逻辑
//从缓存中取商品信息,商品id对应的信息
String json = jedisClientSingle.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 {
//把商品信息写入缓存
jedisClientSingle.set(REDIS_ITEM_KEY + ":" + itemId + ":param", JsonUtils.objectToJson(paramItem));
//设置key的有效期
jedisClientSingle.expire(REDIS_ITEM_KEY + ":" + itemId + ":param", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok(paramItem);
}
return TaotaoResult.build(400, "无此商品规格");
}
}
@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);
return result;
}
@RequestMapping("/desc/{itemId}")
@ResponseBody
public TaotaoResult getItemDesc(@PathVariable Long itemId) {
TaotaoResult result = itemService.getItemDesc(itemId);
return result;
}
@RequestMapping("/param/{itemId}")
@ResponseBody
public TaotaoResult getItemParam(@PathVariable Long itemId) {
TaotaoResult result = itemService.getItemParam(itemId);
return result;
}
}
当用户访问商品详情页面时,需要加载商品基本信息。延迟加载商品描述、按需加载商品的规格参数。
由于页面展示商品信息时,需要展示图片列表。多张图片在数据库中存储的格式是存储在同一个字段中使用逗号分隔的。所以商品展示时需要在pojo中做处理。故此在portal中自定义一个商品的pojo类继承TbItem同时新增一个get方法。
//添加此方法拆分图片列表
public String[] getImages() {
if (image != null && image != "") {
String[] strings = image.split(",");
return strings;
}
return null;
}
商品基本信息的查询:
接收商品id调用mapper查询商品规格参数,返回规格参数pojo使用TaotaoResult包装。添加缓存逻辑。
商品描述延迟加载:
接收商品id,调用taotao-rest的服务,查询商品的基本信息。得到一个json字符串。需要把json转换成java对象。然后在jsp页面渲染。
商品规格参数展示:
接收商品id,调用taotao-rest的服务根据商品id查询商品描述信息。得到json数据。把json转换成java对象从java对象中把商品描述取出来。返回商品描述字符串。
参数:商品id
返回值:字符串(商品描述的html片段)
/**
* 商品内容展示Service
* @author JY
*
*/
@Service
public class ItemServiceImpl implements ItemService {
@Value("${ITEM_INFO_URL}")
private String ITEM_INFO_URL;
@Value("${REST_BASE_URL}")
private String REST_BASE_URL;
@Value("${ITEM_DESC_URL}")
private String ITEM_DESC_URL;
@Value("${ITEM_PARAM_URL}")
private String ITEM_PARAM_URL;
@Override
public ItemInfo getItemInfoById(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) {
ItemInfo itemInfo = (ItemInfo) taotaoResult.getData();
return itemInfo;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//取商品描述
@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();
return result;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//根据商品id查询规格参数
@Override
public String getItemParam(Long itemId) {
try {
String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_PARAM_URL + itemId);
//把json转换成java对象
TaotaoResult taotaoResult = TaotaoResult.formatToPojo(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("\n");
sb.append(" \n");
for(Map m1:jsonList) {
sb.append(" \n");
sb.append(" "+m1.get("group")+" \n");
sb.append(" \n");
List<Map> list2 = (List<Map>) m1.get("params");
for(Map m2:list2) {
sb.append(" \n");
sb.append(" "+m2.get("k")+" \n");
sb.append(" "+m2.get("v")+" \n");
sb.append(" \n");
}
}
sb.append(" \n");
sb.append("
");
//返回html片段
return sb.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
/**
* 商品内容展示
* @author JY
*
*/
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping("/item/{itemId}")
public String showItem(@PathVariable Long itemId,Model model) {
ItemInfo item = itemService.getItemInfoById(itemId);
model.addAttribute("item", item);
return "item";
}
@RequestMapping(value="/item/desc/{itemId}",produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")
@ResponseBody
public String getItemDesc(@PathVariable Long itemId) {
String itemDescById = itemService.getItemDescById(itemId);
return itemDescById;
}
@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;
}
}
最近看老马打斗地主,真相一拳干碎他的眼镜