二、RabbitMQのあるショッピングモールプロジェクトでの使用例

41619 ワード

一、商品に対して添削して調べる時にメッセージを送る
item-serviceにamqp依存を導入:
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-amqpartifactId>
dependency>

プロファイルでの関連情報の構成
server:
  port: 8081
mybatis:
  type-aliases-package: com.leyou.item.pojo
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/leyou
    username: root
    password: 123456
  application:
    name: item-service #           
  #       
  rabbitmq:
    host: 192.168.248.131
    virtual-host: /
    username: admin
    password: admin
    template:
      exchange: LEYOU.ITEM.EXCHANGE #         
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka
    register-with-eureka: true #        ,         true,true    eureka
  instance:
    lease-renewal-interval-in-seconds: 5 #    , 5s        
    lease-expiration-duration-in-seconds: 15 #    

GoodsServiceにメッセージを送信する方法を追加するには、amqpTemplateオブジェクトを先に注入します.ここでのrouting key,フォーマットはitem.*,*です.メッセージを送信する方法で送信されます.try{}catch(){}を使用するのは、メッセージの送信に異常が発生することを防止し、正常なデータベース保存操作に影響を与えるためです.
private void sendMsg(String type, Long id) {
    try {
        this.amqpTemplate.convertAndSend("item." + type, id);
    } catch (AmqpException e) {
        e.printStackTrace();
    }
}

新規商品の場合、メッセージを送信する必要があります.rooting keyitem.insertで、伝達されたパラメータはinsertと新規商品のidです.
@Transactional//    ,  spu,  spuDetail
public void saveGoods(SpuBo spuBo) {
    //1.  spu,spuBo   spu
    //      
    spuBo.setId(null);
    spuBo.setSaleable(true);
    spuBo.setValid(true);
    spuBo.setCreateTime(new Date());
    spuBo.setLastUpdateTime(spuBo.getCreateTime());
    this.spuMapper.insertSelective(spuBo);
    //2.  spuDetail
    SpuDetail spuDetail = spuBo.getSpuDetail();
    spuDetail.setSpuId(spuBo.getId());
    this.spuDetailMapper.insertSelective(spuDetail);
    //3.  sku   
    saveSkuAndStock(spuBo);

    //               :item.insert,  rooting key
    sendMsg("insert", spuBo.getId());
}

商品を修正する場合も、同様にメッセージを送る必要があります
@Transactional
public void updateGoods(SpuBo spuBo) {
    //   spuId    sku
    Sku record = new Sku();
    record.setSpuId(spuBo.getId());
    List<Sku> skus = this.skuMapper.select(record);
    //       ,   
    if(!CollectionUtils.isEmpty(skus)) {
        skus.forEach(sku -> {
            //     
            this.stockMapper.deleteByPrimaryKey(sku.getId());
        });
        //   sku
        Sku sku = new Sku();
        sku.setSpuId(spuBo.getId());
        this.skuMapper.delete(sku);
    }
    //   sku  stock
    this.saveSkuAndStock(spuBo);
    //   spu
    spuBo.setLastUpdateTime(new Date());
    spuBo.setCreateTime(null);
    spuBo.setValid(null);
    spuBo.setSaleable(null);
    this.spuMapper.updateByPrimaryKeySelective(spuBo);
    //   spu  
    this.spuDetailMapper.updateByPrimaryKeySelective(spuBo.getSpuDetail());
    //          ,    
    sendMsg("update",spuBo.getId());
}

二、ページ静化のマイクロサービスでメッセージを受け取り、静的ページを更新する
goods-webマイクロサービスでも同様に依存を導入し,rabbitMQの構成に関する情報は同上であるが,ここではスイッチの名前を宣言する必要はない
/**
 * @auther Mr.Liao
 * @date 2019/5/17 10:02
 */
@Component
public class GoodsListener {
    @Autowired
    private GoodsHtmlService goodsHtmlService;
    /**
     *                     
     * @param id
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.ITEM.SAVE.QUEUE", durable = "true"),
            exchange = @Exchange(value = "LEYOU.ITEM.EXCHANGE", ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"item.insert","item.update"}
    ))
    public void save(Long id){
        if (id == null){
            return;
        }
        //  createHtml()  ,  spuId      
        this.goodsHtmlService.createHtml(id);
    }

    /**
     *      ,            
     * @param id
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.ITEM.DELETE.QUEUE",durable = "true"),
            exchange = @Exchange(value = "LEYOU.ITEM.EXCHANGE",ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"item.delete"}
    ))
    public void delete(Long id){
        if (id == null){
            return;
        }
        this.goodsHtmlService.deleteHtml(id);
    }
}

三、検索マイクロサービスでインデックスライブラリのデータを更新する
依存性を導入し、rabbitMQを構成し、リスニングメッセージを追加する方法
@Component
public class GoodsListener {
    @Autowired
    private SearchService searchService;

    /**
     *          ,         
     * @param id
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.SEARCH.SAVE.QUEUE",durable = "true"),
            exchange = @Exchange(value = "LEYOU.ITEM.EXCHANGE",ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"item.insert","item.update"}
    ))
    public void save(Long id) throws IOException {
        if (id == null){
            return;
        }
        this.searchService.save(id);

    }

    /**
     *        
     * @param id
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.SEARCH.DELETE.QUEUE",durable = "true"),
            exchange = @Exchange(value = "LEYOU.ITEM.EXCHANGE",ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"item.delete"}
    ))
    public void delete(Long id) throws IOException {
        if (id == null){
            return;
        }
        this.searchService.delete(id);
    }
}

次のサービスにおけるsaveメソッドが投げ出す異常は、上のGoodsListenerに投げ出され、ここでのsaveがまた異常を投げ出すと、springフレームワークは、異常があるか否かに応じて、メッセージを確認するか否か(手動ACK)を決定する
/**
 *           ,       
 * @param id
 * @throws IOException
 */
public void save(Long id) throws IOException {
    //     Id                     
    Spu spu = this.goodsClient.querySpuById(id);
    //              
    Goods goods = this.buildGoods(spu);
    //        
    this.goodsRepository.save(goods);
}

/**
 *           ,      
 * @param id
 */
public void delete(Long id) {
    this.goodsRepository.deleteById(id);
}

四、ユーザー登録時にメール認証コードを送る
user-serviceマイクロサービスで
/**
 *      ,     ,    redis 
 * @param phone
 */
public void sendVerifyCode(String phone) {
    if (StringUtils.isBlank(phone)){
        return;
    }
    //      
    String code = NumberUtils.generateCode(6);
    //      rabbitMQ, sms      ,           
    HashMap<String, String> msg = new HashMap<>();
    msg.put("phone",phone);
    msg.put("code", code);
    this.amqpTemplate.convertAndSend("LEYOU.SMS.EXCHANGE","verifyCode.sms", msg);
    //        redis 
    this.redisTemplate.opsForValue().set(KEY_PREFIX+phone, code, 5, TimeUnit.MINUTES);
}

メールマイクロサービスでは,メッセージを傍受してメールを送信する方法を記述する.
@Component
public class SmsListener {
    @Autowired
    private SmsUtils smsUtils;
    @Autowired
    private SmsProperties smsProperties;
    /**
     *        
     * @param msg
     * @throws ClientException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "LEYOU.SMS.QUEUE",durable = "true"),
            exchange = @Exchange(value = "LEYOU.SMS.EXCHANGE",ignoreDeclarationExceptions = "true", type = ExchangeTypes.TOPIC),
            key = {"verifyCode.sms"}
    ))
    public void sendSms(Map<String, String> msg) throws ClientException {
        if (CollectionUtils.isEmpty(msg)){
            return;
        }
        String phone = msg.get("phone");
        String code = msg.get("code");
        if (StringUtils.isNoneBlank(phone) && StringUtils.isNoneBlank(code)){
            this.smsUtils.sendSms(phone, code, this.smsProperties.getSignName(),this.smsProperties.getVerifyCodeTemplate());
        }
    }
}