序文
言うことができない言葉のない量、これは上の話が続いている:
[まとめ]状態の学校のデザインモードモードモード+ +装飾シンプルな工場パターン本物:()私は何地獄を経て、最終的に注文を提出しますか?
一緒に、いくつかの冗長な繰り返しは、こちらの記事を参照してください。
ビジネスシーン
フロー図、または同じ図中の記事で、我々は、ビューモード、アプリケーションオブザーバモード、メモモードを要約しました:
注文センター:
1、注文センター順序作成
2を、転送順序ステータス(状態モデル)
3、操作ログ記録(+デコレータ単純なファクトリパターン)
4、中心線在庫更新通知ストックセンター
ディスパッチセンター:
1は、センターは地元の在庫棚卸(+ +テンプレートメソッドパターン・ファクトリーモードコマンドモードを使用して)を更新する
。この意味が言っていた:[[まとめ]コマンドデザインパターン学習モード+ +テンプレートメソッドファクトリメソッドの戦闘:どのようにエレガントな更新商品在庫...] [5]
2、メッセージに更新されたインベントリデータ、メッセージ・ディスパッチ・センタ消費(中間モード)
3、メッセージ・キューに、充填されたか否かを判断するキュー、オフラインの必要性が充填された場合ストレージ(メモモード)
4、非同期メッセージの処理結果モニタ(オブザーバーパターン)
このモデルは、我々はステップバイステップで、非常に単純である必要があり、ステップバイステップでは、コード分析を解体します
在庫棚卸センターにメッセージを送ります
注文後、受注センターコールセンター株式控除の在庫、在庫・発送センター、コールセンター、派遣センターは、注文世代、請求書の作成や他のいくつかのタスクのスケジュール設定を選ぶ、独自の在庫控除、WMSに行きます。
ストックセンターを切り離すためには、非同期メッセージを消費するために、メモリキューに派遣センターの内容を送信する必要があります。
コードの実装
ストックセンターは、受注センターへのインタフェースを提供します
/** * 通知库存中心,“提交订单”事件发生了 * @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; }
メモリキューカスタム
/** * 商品库存更新消息的队列接口 * @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(); } }
カスタムメッセージ本文
/** * 商品库存更新消息 * @author wangmeng * */ @Data public class StockUpdateMessage { /** * id */ private String id; /** * 商品库存更新操作 */ private Integer operation; /** * 核心参数数据 */ private Object parameter; }
消費者ニュース派遣センター
/** * 库存更新消息消费者 * @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は、オフラインキューにデータを復元した場合。
コードの実装
キュー上のメッセージ
/** * 将一个消息放入队列 * @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); }
オフラインストレージマネージャー
/** * 离线存储管理组件接口 * @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; } } }
オフラインデータ復旧のカテゴリ
/** * 离线数据恢复线程 * @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); } } }
ストックセンター非同期メッセージ消費者のリスニング結果
実際には、我々はすでにコードの先頭の終わりに、ここで再び、特定の観測、観測者コードの下に掲載非同期モニターの消費の結果を、説明されています。
コードの実装
観察
/** * 商品库存更新结果观察目标 * @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; } }
オブザーバー
/** * 商品库存更新结果观察者 * @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()); } }
オブザーバーを追加します
在庫センターが派遣センターに非同期メッセージを送信する際の方法注文センター通知センターの在庫更新のインベントリと呼ばれるを観察し、観察者に追加ニュースを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は、ソースを明記してください転載必要があります!
興味のパートナーは、個々の国民の少数心配することができる:一つの枝にはロマンチックな花を数えます