Spring MultiValueMap抛出java.lang.UnsupportedOperationException: null异常

今儿在SC-Gateway处理formData的时候,明明有值,但是会抛出java.lang.UnsupportedOperationException: null的异常。

看一下代码:

1
2
3
4
5
6
7
8
if (delegate.getMethod().matches("POST")) {
if (StringUtils.equals(mediatype.toString(), MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
Mono<MultiValueMap<String, String>> formdata = exchange.getFormData();
addFormDataToMap(formdata, paramsMap);
} else {
...
}
}

Spring Cloud Gateway是建在Spring 5和Spring Boot 2.0之上的。所以是响应式的编程,上手比较困难。这里是做一个FormData的转换,将键值对形式的FormData加载到Query中去,再继续做下一步操作。

addFormDataToMap方法是这样的:

1
2
3
4
5
6
7
8
9
10
11
public void addFormDataToMap(Mono<MultiValueMap<String, String>> formdata,
MultiValueMap<String, String> paramsMap) {
AtomicReference<MultiValueMap<String, String>> QueryRef = new AtomicReference<>();
formdata.subscribe(maps -> {
QueryRef.set(maps);
});
if (QueryRef.get().isEmpty() && QueryRef.get() == null) {
return;
}
paramsMap.addAll(QueryRef.get()); // <1>
}

paramsMap存储的是Query中的键值对,同过formdata的subscribe,存储进QueryRef中。最后在addAllparamsMap

这样看起来没什么问题,但是当执行<1>时,会抛出异常:java.lang.UnsupportedOperationException: null

跟进去发现,在CollectionUtils类中,可以看到存在完整的键值对,执行完当前step会直接抛出异常。

subscribe抛出异常:

查看java.util.Map方法中的computeIfAbsent类,当当前Map不支持此put操作时抛出UnsupportedOperationException异常,所以存储了一个null

修改代码:

1
2
3
4
5
6
7
8
9
10
11
public void addFormDataToMap(Mono<MultiValueMap<String, String>> formdata, MultiValueMap<String, String> paramsMap) {
AtomicReference<MultiValueMap<String, String>> queryRef = new AtomicReference<>();
formdata.subscribe(maps -> {
queryRef.set(maps);
});
if (queryRef.get() == null && queryRef.get().isEmpty()) {
return;
}
LinkedMultiValueMap<String, String> newList = new LinkedMultiValueMap<>(paramsMap); // {1-1}
newList.addAll(queryRef.get()); // {1-2}
}

删除原先代码<1>部分,增加{1-1}{1-2},先创建新的LinkedList,再addAll

引用

Why do I get an UnsupportedOperationException when trying to remove an element from a List?🔚


Buy Me A Coffee.