今天阳光明媚,掐指一算,今天比较适合划水。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; }