今天陽光明媚,掐指一算,今天比較適合划水。java
因而早上到公司以後先是蹲了廁所,而後就準備翻閱公衆號推文。工具
看的正嗨,忽然釘釘羣裏開始響了,post
生產日誌羣報了一條警告,以下:學習
報錯信息很明確阿里雲
UnsupportedOperationException java.lang.UnsupportedOperationException at java.util.AbstractMap.put(AbstractMap.java:209) at com.ifugle.rap.dsb.bot.service.messageBus.chatResult.postProcessor.BizCategoryResultResolveProcessor.concatBizCategoryChatResult(BizCategoryResultResolveProcessor.java:98)
定位到業務代碼以下3d
/** * 拼接業務多輪聊天結果 * * @param utterance * @param chatResult */ private void concatBizCategoryChatResult(String utterance, Map<String, Object> chatResult) { Object botAction = bizCategoryChatResult.get(MESSAGE_BOT_ACTION); if (NullUtil.isNotNull(botAction)) { chatResult.put(MESSAGE_BOT_ACTION, botAction);//--->這行代碼報錯 chatResult.put(DISPLAY_CONTENT, bizCategoryChatResult.get(DISPLAY_CONTENT)); chatResult.put(MESSAGE_BOT_FRAMEWORK, bizCategoryChatResult.get(MESSAGE_BOT_FRAMEWORK)); } }
一個普普統統的map的put操做,怎麼就報錯了呢?繼續往下看。日誌
報錯是在AbstractMap,翻看源碼code
public V put(K key, V value) { throw new UnsupportedOperationException(); }
這個抽象累定義了一個public的put方法,可是裏面是直接拋出了異常。orm
分析一下,應該是某個類繼承了AbstractMap這個類,可是又沒有重寫put方法,因而就直接調用了父類的put方法致使直接拋異常了。對象
我又翻看了阿里雲上的日誌發現傳過來的這個map是一個空的。
個人第一反應就是集合工具類Collections裏面的靜態方法emptyMap(),由於咱們業務代碼中有不少地方都用到了這個。
這裏貼一小段代碼
if (!continueSendToRobot) { chatResult = toManResult.getResult(); if (chatResult == null) { chatResult = EMPTY_CHAT_RESULT;//<---- 看到這個EMPTY_CHAT_RESULT沒 } chatMessageForm.setChatResult(chatResult); return ExitHandle.class; }
這個是個靜態變量,因而我又找到了定義它的地方
// 空的聊天內容 Map<String, Object> EMPTY_CHAT_RESULT = Collections.emptyMap();
繼續看這個emptyMap()
public static final <K,V> Map<K,V> emptyMap() { return (Map<K,V>) EMPTY_MAP; } //又是一個靜態變量 //繼續看 public static final Map EMPTY_MAP = new EmptyMap<>(); //這裏是new了一個EmptyMap對象 //繼續看這個對象,若是這個對象是繼承了AbstractMap剛好它沒有重寫put方法的話,那就證實個人猜測每問題 private static class EmptyMap<K,V> extends AbstractMap<K,V> implements Serializable //能夠看到這個EmptyMap是Collections的一個靜態內部類,繼承了AbstractMap
再看看這個類的全部方法
能夠看到該類並無重寫put方法!
破案了!
那麼問題來了,怎麼解決呢?
後面我在業務代碼裏面加了一個判斷邏輯,當這個map是AbstractMap而且是一個空map時,從新給他new一個HashMap。
錯誤示範請勿參考!
/** * 拼接業務多輪聊天結果 * * @param utterance * @param chatResult */ private void concatBizCategoryChatResult(String utterance, Map<String, Object> chatResult) { // 新加代碼 if (NullUtil.isNull(chatResult) && chatResult instanceof AbstractMap) { chatResult = new HashMap<>(); } Object botAction = bizCategoryChatResult.get(MESSAGE_BOT_ACTION); if (NullUtil.isNotNull(botAction)) { chatResult.put(MESSAGE_BOT_ACTION, botAction);//--->這行代碼報錯 chatResult.put(DISPLAY_CONTENT, bizCategoryChatResult.get(DISPLAY_CONTENT)); chatResult.put(MESSAGE_BOT_FRAMEWORK, bizCategoryChatResult.get(MESSAGE_BOT_FRAMEWORK)); } }
至此,問題就解決啦~~
繼續划水。
更新一下,很是感謝@mrfangzheng在評論裏面的指正,我上面這種BUG的修復方案是錯誤的,學習了謝謝!
我如今的解決方案就是把這個map返回回去,也是這位老哥給的建議,再次感謝。
修正版以下
/** * 拼接業務多輪聊天結果 * * @param utterance * @param chatResult */ private Map<String, Object> concatBizCategoryChatResult(String utterance, Map<String, Object> chatResult) { // 新加代碼 if (NullUtil.isNull(chatResult) && chatResult instanceof AbstractMap) { chatResult = new HashMap<>(); } Object botAction = bizCategoryChatResult.get(MESSAGE_BOT_ACTION); if (NullUtil.isNotNull(botAction)) { chatResult.put(MESSAGE_BOT_ACTION, botAction);//--->這行代碼報錯 chatResult.put(DISPLAY_CONTENT, bizCategoryChatResult.get(DISPLAY_CONTENT)); chatResult.put(MESSAGE_BOT_FRAMEWORK, bizCategoryChatResult.get(MESSAGE_BOT_FRAMEWORK)); } return chatResult; }