一.添加商品同步索引库-MessageListener
1.search-service的spring中需配置connenction工厂,destination的两个对象,监听器,监听容器
1.在search-service下书写一个SearchItemMessageListener实现接口MessageListener,它的重写方法onmessage完成查询目标商品并更新到索引库,并交付给spring管理;代码如下:
public class SearchItemListener implements MessageListener { @Autowired private ItemMapper itemMapper; @Autowired private SolrServer solrServer; public void onMessage(Message message) { TextMessage itemId = (TextMessage) message; try { //获取id String id_str = itemId.getText(); long id = Long.parseLong(id_str); //根据id查询商品 SearchItem item = itemMapper.getItemById(id); //创建文档 SolrInputDocument document = new SolrInputDocument(); //添加域 document.addField("id", item.getId()); document.addField("price", item.getPrice()); document.addField("image", item.getImage()); //添加文档 solrServer.add(document); //提交 solrServer.commit(); } catch (Exception e) { e.printStackTrace(); } } }
二.添加商品同步索引库-发送消息
1.可以添加发送信息代码的地方有两处:
》在manager-service的addItem方法结尾添加;该方案有个缺点,即在事务没有完成提交就已经把消息发送出来了,最坏的情况是没有提交同步到数据库时,另一端就已经先收到消息并查询数据库,导致查询结果为空
》在manager-web调用manager-service的addItem方法完成后添加;该方案相对靠谱点,在manager-service的addItem方法结束,必定事务已经完成,此时发送消息,另一端接收并查询就能保证查到
2.在manager-web配置connection工厂,生产者jmstemplate,destination两个对象(一般使用topic会比较多,因为除了同步索引库,还要缓存等待也需要消息);
3.完成发送消息代码:
public @ResponseBody E3Result addItem(TbItem item,String desc) { //添加单个商品 E3Result result = itemService.addItem(item, desc); //发送信息 jmsTemplate.send(destination, new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { TextMessage message = session.createTextMessage(); message.setText("hello world activemq"); return message; } }); return result; }
三.商品详情页面工程搭建
》建立表现层工程item_web,目录结构参照其他表现层
四.商品详情页面展示分析
》由于页面涉及到商品的images这个属性,恰巧逆向工程生成的TbItem没有images属性,我们在item-web工程创建一个pojo为Item继承于TbItem,添加images属性即可
》Item类只用于item-web,所以也不需要实现序列化接口
1 public class Item extends TbItem{ 2 3 public Item(TbItem tbItem) { 4 5 this.setId( tbItem.getId() ); 6 this.setTitle(tbItem.getTitle()); 7 this.setStatus(tbItem.getStatus()); 8 } 9 10 //获取属性images 11 public String[] getImages() { 12 13 String image = this.getImage(); 14 15 if( image != null && !image.equals("") ) { 16 17 return image.split(","); 18 } 19 return null; 20 } 21 22 }
四.商品详情页面展示-代码实现
》item-web要调用manager-service的ItemService根据id查询商品和商品描述
》item-web的controller:
public class ItemController { @Autowired private ItemService itemService; @RequestMapping("/item/{itemId}") public String showItemInfo(@PathVariable("itemId") long itemId,Model model) { //查询商品 TbItem tbItem = itemService.getItemById(itemId); //转换TbItem成Item Item item = new Item(tbItem); //查询商品描述 TbItemDesc desc = itemService.getItemDescById(itemId); //添加到model model.addAttribute("item",item); model.addAttribute("itemDesc",desc); //返回逻辑视图 return "item.jsp"; } }
》manager-service的service:
public interface ItemService { //按ID查询商品 public TbItem getItemById(long itemId); //获取商品列表 public EasyUiDataGridResult getItemList(Integer page,Integer rows); //添加商品 public E3Result addItem(TbItem item,String desc); //按ID查询商品描述 public TbItemDesc getItemDescById(long itemId); }
五.商品信息添加缓存-分析
》考虑到商品详情页面在普通的互联网项目,并发量是挺高的,我们需要给manager-service查询商品和描述添加缓存
》给商品详情添加缓存时还得考虑一点,有的页面是访问流很小的,这种长期缓存在内存中是十分浪费的,所以计划每一次的缓存数据设置过期时间(时间视商品情况而定),适当得减少数据库的压力,又可以减少内存的消耗
》数据类型得采用String,不用hash的原因是hash的key设置不了过期时间;使用String类型最好加前缀甚至后缀来 区分不同分类的数据:
六.向业务逻辑中添加缓存
》添加缓存时一定得加try-catch,避免redis出现异常导致数据库操作失败
》查询完数据马上缓存,不要等返回数据才缓存
public TbItem getItemById(long itemId) { String redis_item = ""; try { redis_item = jedisClient.get("ITEM-INFO"+itemId+"BASE"); } catch (Exception e) { e.printStackTrace(); } //判断是否缓存 if( redis_item != null && !redis_item.equals("") ) { return (TbItem) JSONUtils.parse(redis_item); } //按条件对象查询 TbItemExample example = new TbItemExample(); Criteria criteria = example.createCriteria(); criteria.andIdEqualTo(itemId); List<TbItem> list = itemMapper.selectByExample(example); //缓存数据 try { if( list.size() > 0 && list != null ) { jedisClient.set("ITEM-INFO"+itemId+"BASE", itemId+""); jedisClient.expire("ITEM-INFO"+itemId+"BASE", 3600); } return list.get(0); } catch (Exception e) { // TODO: handle exception } return null; }
七.删除重复记录