[共同]メディエータのデザインパターンの学習モードオブザーバモード+ +メモ戦闘モード:( II)私は何地獄を経て、最終的に注文を提出しますか?

序文

言うことができない言葉のない量、これは上の話が続いている:
[まとめ]状態の学校のデザインモードモードモード+ +装飾シンプルな工場パターン本物:()私は何地獄を経て、最終的に注文を提出しますか?
一緒に、いくつかの冗長な繰り返しは、こちらの記事を参照してください。

ビジネスシーン

フロー図、または同じ図中の記事で、我々は、ビューモード、アプリケーションオブザーバモード、メモモードを要約しました:

17C4F70C-E159-4AD8-B394-232A54F52F01.png

注文センター:
1、注文センター順序作成
2を、転送順序ステータス(状態モデル)
3、操作ログ記録(+デコレータ単純なファクトリパターン)
4、中心線在庫更新通知ストックセンター

ディスパッチセンター:
1は、センターは地元の在庫棚卸(+ +テンプレートメソッドパターン・ファクトリーモードコマンドモードを使用して)を更新する
。この意味が言っていた:[[まとめ]コマンドデザインパターン学習モード+ +テンプレートメソッドファクトリメソッドの戦闘:どのようにエレガントな更新商品在庫...] [5]
2、メッセージに更新されたインベントリデータ、メッセージ・ディスパッチ・センタ消費(中間モード)
3、メッセージ・キューに、充填されたか否かを判断するキュー、オフラインの必要性が充填された場合ストレージ(メモモード)
4、非同期メッセージの処理結果モニタ(オブザーバーパターン)

このモデルは、我々はステップバイステップで、非常に単純である必要があり、ステップバイステップでは、コード分析を解体します

在庫棚卸センターにメッセージを送ります

注文後、受注センターコールセンター株式控除の在庫、在庫・発送センター、コールセンター、派遣センターは、注文世代、請求書の作成や他のいくつかのタスクのスケジュール設定を選ぶ、独自の在庫控除、WMSに行きます。

ストックセンターを切り離すためには、非同期メッセージを消費するために、メモリキューに派遣センターの内容を送信する必要があります。

コードの実装

  1. ストックセンターは、受注センターへのインタフェースを提供します

    /**
     * 通知库存中心,“提交订单”事件发生了
     * @param orderDTO 订单DTO
     * @return 处理结果
     */
    @Override
    public Boolean informSubmitOrderEvent(OrderInfoDTO orderDTO) {
        try {
            // 更新本地库存
            // do logic
    
            // 发送异步消息到内存队列
            StockUpdateMessage message = new StockUpdateMessage();
            message.setId(UUID.randomUUID().toString().replace("-", ""));   
            message.setOperation(GoodsStockUpdateOperation.SUBMIT_ORDER);
            message.setParameter(orderDTO);  
            goodsStockUpdateQueue.put(message);
    
            // 监听异步处理结果
            goodsStockUpdateManager.observe(message.getId());  
        } catch (Exception e) {
            logger.error("error", e); 
            return false;
        }
        return true;
    }
  2. メモリキューカスタム

    
    /**
     * 商品库存更新消息的队列接口
     * @author wangmeng
     *
     */
    public interface StockUpdateQueue {
    
        /**
         * 将一个消息放入队列
         * @param message 消息
         * @throws Exception
         */
        void put(StockUpdateMessage message) throws Exception;
    
        /**
         * 直接将消息放入队列
         * @param message
         * @throws Exception
         */
        void putDirect(StockUpdateMessage message) throws Exception;
    
        /**
         * 从队列中取出一个消息
         * @return
         * @throws Exception
         */
        StockUpdateMessage take() throws Exception;
    
        /**
         * 获取队列大小
         * @return
         * @throws Exception
         */
        Integer size() throws Exception;
    }
    
    /**
     * 商品库存更新队列实现类
     * @author wangmeng
     *
     */
    @Component
    public class StockUpdateQueueImpl implements StockUpdateQueue {
    
        private static final Integer QUEUE_MAX_SIZE = 1000;
    
        /**
         * 离线存储管理组件
         */
        @Autowired
        private OfflineStorageManager offlineStorageManager;
    
        /**
         * 商品库存更新队列
         */
        private ArrayBlockingQueue<StockUpdateMessage> queue = 
                new ArrayBlockingQueue<StockUpdateMessage>(QUEUE_MAX_SIZE); 
    
        /**
         * 将一个消息放入队列
         * @param message 消息
         * @throws Exception
         */
        @Override
        public void put(StockUpdateMessage message) throws Exception {
            queue.put(message); 
        }
    
        /**
         * 从队列中取出一个消息
         * @return
         * @throws Exception
         */
        @Override
        public StockUpdateMessage take() throws Exception { 
            return queue.take();
        }
    
        /**
         * 直接将消息放入队列
         * @param message
         * @throws Exception
         */
        @Override
        public void putDirect(StockUpdateMessage message) throws Exception {
            queue.put(message); 
        }
    
        /**
         * 获取队列大小
         * @return
         * @throws Exception
         */
        @Override
        public Integer size() throws Exception {
            return queue.size();
        }
    
    }
  3. カスタムメッセージ本文

    /**
     * 商品库存更新消息
     * @author wangmeng
     *
     */
     @Data
    public class StockUpdateMessage {
    
        /**
         * id
         */
        private String id;
        /**
         * 商品库存更新操作
         */
        private Integer operation;
        /**
         * 核心参数数据
         */
        private Object parameter;
    }
  4. 消費者ニュース派遣センター

    /**
     * 库存更新消息消费者
     * @author wangmeng
     *
     */
    @Component
    public class ScheduleStockUpdateMessageConsumer extends Thread {
    
        private static final Logger logger = LoggerFactory.getLogger(
                ScheduleStockUpdateMessageConsumer.class);
    
        /**
         * 库存更新消息队列
         */
        @Autowired
        private StockUpdateQueue stockUpdateQueue;
        /**
         * 调度中心接口
         */
        @Autowired
        private ScheduleService scheduleService;
        /**
         * 库存中心的消息管理器
         */
        @Autowired
        private StockUpdateResultManager stockUpdateResultManager;
    
        /**
         * 消费库存更新消息
         */
        @Override
        public void run() {
            while(true) {
                try {
                    StockUpdateMessage message = stockUpdateQueue.take();
                    if(!isOrderRelatedMessage(message)) {
                        continue;
                    }
                    OrderInfoDTO order = getOrderFromMessage(message);
                    processMessage(message, order);
                    stockUpdateResultManager.inform(message.getId(), true); 
                } catch (Exception e) {
                    logger.error("error", e); 
                }
            }
        }
    
        /**
         * 是否是订单相关的操作
         * @param message 消息
         * @return 是否是订单相关的操作
         * @throws Exception
         */
        private Boolean isOrderRelatedMessage(StockUpdateMessage message) throws Exception {
            return GoodsStockUpdateOperation.SUBMIT_ORDER.equals(message.getOperation())
                    || GoodsStockUpdateOperation.CANCEL_ORDER.equals(message.getOperation()) 
                    || GoodsStockUpdateOperation.PAY_ORDER.equals(message.getOperation());
        }
    
        /**
         * 从消息中获取订单
         * @param message 消息
         * @return 订单
         * @throws Exception
         */
        private OrderInfoDTO getOrderFromMessage(StockUpdateMessage message) throws Exception {
            return (OrderInfoDTO) message.getParameter();
        }
    
        /**
         * 处理消息
         * @param order 订单 
         * @return 处理结果
         * @throws Exception
         */
        private Boolean processMessage(StockUpdateMessage message, 
                OrderInfoDTO order) throws Exception {
            if(GoodsStockUpdateOperation.SUBMIT_ORDER.equals(message.getOperation())) {
                return scheduleService.informSubmitOrderEvent(order);
            } else if(GoodsStockUpdateOperation.CANCEL_ORDER.equals(message.getOperation())) {
                return scheduleService.informCancelOrderEvent(order);
            } else if(GoodsStockUpdateOperation.PAY_ORDER.equals(message.getOperation())) {
                return scheduleService.informPayOrderEvent(order);
            }
            return false;
        }
    
    }

、メッセージキューをリスニング完全なメッセージを防止

ここでは、我々は消費者が異常であるか、遅すぎる消費を行う方法をメッセージの混雑につながっている場合は考慮する必要があり、ブロックキューメモリを使うのか?

それはその後、DBへの保存、オフラインストレージに追加された場合、キューが、満杯であればここでは、メモモード記録キューを使用しています。キューサイズ= 0は、オフラインキューにデータを復元した場合。

コードの実装

  1. キュー上のメッセージ

    /**
     * 将一个消息放入队列
     * @param message 消息
     * @throws Exception
     */
    public void put(StockUpdateMessage message) throws Exception {
        // 每次要往内存队列放消息之前,先检查一下离线存储标识
        // 如果触发了离线存储,直接就往离线存储去写入,不要走后面的逻辑了
        // 写完离线存储之后,需要检查一下内存队列的大小,如果内存队列已经清零,则启动一个后台线程
        // 让后台线程去将离线存储中的数据恢复写入内存队列中
        if(offlineStorageManager.getOffline()) {
            offlineStorageManager.store(message); 
    
            if(queue.size() == 0) {
                new OfflineResumeThread(offlineStorageManager, this).start(); 
            }
    
            return;
        }
    
        // 如果内存队列已经满了,此时就触发离线存储
        if(QUEUE_MAX_SIZE.equals(queue.size())) {  
            offlineStorageManager.store(message); 
            offlineStorageManager.setOffline(true);
            return;
        }
    
        queue.put(message); 
    }
  2. オフラインストレージマネージャー

    /**
     * 离线存储管理组件接口
     * @author wangmeng
     *
     */
    public interface OfflineStorageManager {
    
        /**
         * 离线存储库存更新消息
         * @param message 库存更新消息
         * @throws Exception
         */
        void store(StockUpdateMessage message) throws Exception;
    
        /**
         * 获取离线存储标识
         * @return 离线存储标识
         * @throws Exception
         */
        Boolean getOffline() throws Exception;
    
        /**
         * 设置离线存储标识
         * @param offline 离线存储标识
         * @throws Exception
         */
        void setOffline(Boolean offline) throws Exception;
    
        /**
         * 所谓的迭代器模式,什么时候用?
         * 
         * 其实只有一个场景,就是如果你需要基于一些不支持迭代的数据,来让我们业务代码进行迭代
         * 那么你自己就要去实现基于那个数据的一套迭代代码
         * 以迭代器的方式返回回去给业务方,来通过你定义的迭代器,进行数据的迭代
         * 
         * mysql数据库,本身是不支持迭代式访问的,但是我们可以自己实现一套基于mysql的迭代访问的代码
         * 把一个迭代器给返回回去
         * 
         * 比如有的时候,我们可能还需要基于es、redis的数据,来提供业务方迭代式访问的功能,那么此时就只能我们自己
         * 去封装迭代器,在里面封装基于es、redis的迭代访问数据的逻辑
         * 
         */
        /**
         * 获取迭代器
         * @return 迭代器
         * @throws Exception
         */
        OfflineStorageIterator iterator() throws Exception;
    
        /**
         * 批量删除库存更新消息
         * @param stockUpdateMessages 库存更新消息
         * @throws Exception
         */
        void removeByBatch(List<StockUpdateMessage> stockUpdateMessages) throws Exception;
    }
    
    /**
     * 离线存储管理组件
     * @author wangmeng
     *
     */
    @Component
    public class OfflineStorageManagerImpl implements OfflineStorageManager {
    
        /**
         * 库存更新消息管理模块DAO组件
         */
        @Autowired
        private StockUpdateMessageDAO stockUpdateMessageDAO;
    
        /**
         * 是否触发离线存储的标识
         */
        private Boolean offline = false;
    
        /**
         * 离线存储库存更新消息
         * @param message 库存更新消息
         * @throws Exception
         */
        @Override
        public void store(StockUpdateMessage message) throws Exception {
            StockUpdateMessageDO stockUpdateMessageDO = createStockUpdateMessageDO(message);
            stockUpdateMessageDAO.save(stockUpdateMessageDO);
        }
    
        /**
         * 创建库存更新消息DO对象
         * @param message 库存更新消息
         * @return 库存更新消息DO对象
         * @throws Exception
         */
        private StockUpdateMessageDO createStockUpdateMessageDO(
                StockUpdateMessage message) throws Exception {
            StockUpdateMessageDO stockUpdateMessageDO = new StockUpdateMessageDO();
            stockUpdateMessageDO.setMessageId(message.getId());
            stockUpdateMessageDO.setOperation(message.getOperation());
            stockUpdateMessageDO.setParameter(JSONObject.toJSONString(message.getParameter())); 
            stockUpdateMessageDO.setParamterClazz(message.getParameter().getClass().getName());  
            stockUpdateMessageDO.setGmtCreate(new Date()); 
            stockUpdateMessageDO.setGmtModified(new Date()); 
            return stockUpdateMessageDO;
        }
    
        /**
         * 获取离线存储标识
         * @return 离线存储标识
         * @throws Exception
         */
        @Override
        public Boolean getOffline() throws Exception {
            return offline;
        }
    
        /**
         * 设置离线存储标识
         * @param offline 离线存储标识
         * @throws Exception
         */
        @Override
        public void setOffline(Boolean offline) throws Exception {
            this.offline = offline;
        }
    
        /**
         * 批量删除库存更新消息
         * @param stockUpdateMessages 库存更新消息
         * @throws Exception
         */
        @Override
        public void removeByBatch(List<StockUpdateMessage> stockUpdateMessages) throws Exception {
            StringBuilder builder = new StringBuilder("");
            for(int i = 0; i < stockUpdateMessages.size(); i++) {
                builder.append(stockUpdateMessages.get(i).getId());
                if(i < stockUpdateMessages.size() - 1) {
                    builder.append(","); 
                }
            }
            stockUpdateMessageDAO.removeByBatch(builder.toString());
        }
    
        /**
         * 获取离线数据迭代器
         * @throws Exception
         */
        @Override
        public OfflineStorageIterator iterator() throws Exception {
            return new OfflineStorageIteratorImpl();
        }
    
        /**
         * 离线数据迭代器
         * @author zhonghuashishan
         *
         */
        public class OfflineStorageIteratorImpl implements OfflineStorageIterator {
    
            /**
             * 判断是否还有下一批库存更新消息
             * @return 是否还有下一批库存更新消息
             * @throws Exception
             */
            @Override
            public Boolean hasNext() throws Exception {
                return stockUpdateMessageDAO.count().equals(0L) ? false : true;
            }
    
            /**
             * 获取下一批库存更新消息
             * @return 下一批库存更新消息
             * @throws Exception
             */
            @Override
            public List<StockUpdateMessage> next() throws Exception {
                List<StockUpdateMessage> stockUpdateMessages = new ArrayList<StockUpdateMessage>();
    
                List<StockUpdateMessageDO> stockUpdateMessageDOs = 
                        stockUpdateMessageDAO.listByBatch();
                for(StockUpdateMessageDO stockUpdateMessageDO : stockUpdateMessageDOs) {
                    StockUpdateMessage stockUpdateMessage = new StockUpdateMessage();
                    stockUpdateMessage.setId(stockUpdateMessageDO.getMessageId()); 
                    stockUpdateMessage.setOperation(stockUpdateMessageDO.getOperation()); 
                    stockUpdateMessage.setParameter(JSONObject.parseObject(stockUpdateMessageDO.getParameter(), 
                            Class.forName(stockUpdateMessageDO.getParamterClazz())));  
                    stockUpdateMessages.add(stockUpdateMessage);
                }
    
                return stockUpdateMessages;
            }
        }
    }
  3. オフラインデータ復旧のカテゴリ

    /**
     * 离线数据恢复线程
     * @author wangmeng
     *
     */
    public class OfflineResumeThread extends Thread {
    
        private static final Logger logger = LoggerFactory.getLogger(OfflineResumeThread.class);
    
        /**
         * 离线存储管理组件
         */
        private OfflineStorageManager offlineStorageManager;
        /**
         * 库存更新队列
         */
        private StockUpdateQueue stockUpdateQueue;
    
        /**
         * 构造函数
         * @param offlineStorageManager 离线存储管理组件
         */
        public OfflineResumeThread(OfflineStorageManager offlineStorageManager,
                StockUpdateQueue stockUpdateQueue) {
            this.offlineStorageManager = offlineStorageManager;
            this.stockUpdateQueue = stockUpdateQueue;
        }
    
        /**
         * 执行线程
         */
        @Override
        public void run() {
            try {
                // 如果表中还有数据的话
                OfflineStorageIterator offlineStorageIterator = offlineStorageManager.iterator();
    
                while(offlineStorageIterator.hasNext()) {
                    try {
                        // 每次就从mysql中查询50条数据,批量查询,批量处理,批量删除
                        List<StockUpdateMessage> stockUpdateMessages = offlineStorageIterator.next();
    
                        // 将这批数据写入内存队列中
                        for(StockUpdateMessage message : stockUpdateMessages) {
                            stockUpdateQueue.putDirect(message);
                        }
    
                        // 批量删除这批数据
                        offlineStorageManager.removeByBatch(stockUpdateMessages); 
                    } catch (Exception e) {
                        logger.error("error", e); 
                    }
                }
    
                // 此时mysql中的数据全部恢复完,更新内存标识
                offlineStorageManager.setOffline(false); 
            } catch (Exception e) {
                logger.error("error", e); 
            }
        }
    }

ストックセンター非同期メッセージ消費者のリスニング結果

実際には、我々はすでにコードの先頭の終わりに、ここで再び、特定の観測、観測者コードの下に掲載非同期モニターの消費の結果を、説明されています。

コードの実装

  1. 観察

    /**
     * 商品库存更新结果观察目标
     * @author wangmeng
     *
     */
    public class StockUpdateObservable extends Observable {
    
        /**
         * 消息id
         */
        private String messageId;
    
        /**
         * 构造函数
         * @param messageId 消息id
         */
        public StockUpdateObservable(String messageId) {
            this.messageId = messageId;
        }
    
        /**
         * 设置商品库存更新结果
         * @param result 商品库存更新结果
         */
        public void setResult(Boolean result) {
            StockUpdateResult goodsStockUpdateResult = new StockUpdateResult();
            goodsStockUpdateResult.setMessageId(messageId); 
            goodsStockUpdateResult.setResult(result); 
    
            this.setChanged();
            this.notifyObservers(goodsStockUpdateResult);  
        }
    
        public String getMessageId() {
            return messageId;
        }
    }
  2. オブザーバー

    /**
     * 商品库存更新结果观察者
     * @author wangmeng
     *
     */
    @Component
    public class StockUpdateObserver implements Observer {
    
        private static final Logger logger = LoggerFactory.getLogger(
                StockUpdateObserver.class);
    
        /**
         * 通知异步处理结果
         */
        @Override
        public void update(Observable o, Object arg) {
            StockUpdateResult result = (StockUpdateResult) arg;
            logger.info("商品库存更新消息[messageId=" + result.getMessageId() + "]" 
                    + "的异步处理结果为:" + result.getResult());    
        }
    }
  3. オブザーバーを追加します

在庫センターが派遣センターに非同期メッセージを送信する際の方法注文センター通知センターの在庫更新のインベントリと呼ばれるを観察し、観察者に追加ニュースをMESSAGEID。

派遣センターは、消費者が成功した場合、メッセージ呼び出しの消費者に通知することで、派遣センターの呼び出しは、メソッド、結果セット=真を知らせます

```java
/**
 * 商品库存更新结果管理组件
 * @author wangmeng
 *
 */
@Component
public class StockUpdateResultManagerImpl 
        implements StockUpdateResultManager {

    /**
     * 商品库存更新结果map
     */
    private Map<String, StockUpdateObservable> observableMap = 
            new ConcurrentHashMap<String, StockUpdateObservable>();

    /**
     * 商品库存更新结果观察者
     */
    @Autowired
    private StockUpdateObserver observer;

    /**
     * 设置对商品库存更新结果的观察
     * @param messageId 消息id
     * @param result 商品库存更新结果
     * @param observer 商品库存更新结果的观察者
     */
    @Override
    public void observe(String messageId) {
        StockUpdateObservable observable = new StockUpdateObservable(messageId);
        observable.addObserver(observer);  
        observableMap.put(messageId, observable);
    }

    /**
     * 获取商品库存更新结果的观察目标
     * @param messageId 商品库存更新消息id
     * @return 商品库存更新结果的观察目标
     */
    @Override
    public void inform(String messageId, Boolean result) {
        StockUpdateObservable observable = observableMap.get(messageId);
        observable.setResult(result); 
        observableMap.remove(messageId);
    }

    /**
     * 获取库存更新结果观察目标
     * @param messageId 消息id
     * @return
     */
    @Override
    public StockUpdateObservable getObservable(String messageId) {
        return observableMap.get(messageId);
    }

}
```

概要

もう少しこの部分では、主に3つのブロックに分割し、その後中間モデル、メモモード、観察モードを組み合わせます。

前記回復オフラインクラスのメッセージや、反復モードを使用します。

コードは、私はそれが非常に簡単に読み取ることがまだあると信じて、離れたシンプルなプルを行うには、デザインパターン最初のシリーズは終わりに来て、これらの記事は、新しいモデルが更新を継続する場合、いくつかの一般的なデザインパターンをバック伴います。

宣言

:私のブログから始まるこの記事https://www.cnblogs.com/wang-mengと公共番号:ロマンチックみなさ一つramiflorous BEは、ソースを明記してください転載必要があります!

興味のパートナーは、個々の国民の少数心配することができる:一つの枝にはロマンチックな花を数えます

22.jpg

おすすめ

転載: www.cnblogs.com/wang-meng/p/12079082.html