e3mall_day09

一.添加商品同步索引库-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;
    }

 七.删除重复记录

原文地址:https://www.cnblogs.com/ibcdwx/p/13549648.html