背景

最近使用SpringRestTemplate工具类请求接口,Post请求取不到参数,而Get请求是正常的。后面深入发现Map定义成以下两种类型是取不到参数的:

1
2
3
Map<String, String> paramMap = new HashMap<g>();

Map<String, String> paramMap = new LinkedHashMap<>();

而当我把Map改成LinkedMultiValueMap后,后台能正常取到参数:

1
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();

MultiValueMap

首先看LinkedMultiValueMap,实现MultiValueMap接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface MultiValueMap<K, V> extends Map<K, List<V>> {
@Nullable
V getFirst(K var1);

void add(K var1, @Nullable V var2);

void addAll(K var1, List<? extends V> var2);

void addAll(MultiValueMap<K, V> var1);

void set(K var1, @Nullable V var2);

void setAll(Map<K, V> var1);

Map<K, V> toSingleValueMap();
}

可以看出,LinkedMultiValueMap实际就是Key-LinkedListMap

RestTemplate POST处理请求方式

查看RestTemplate源码,首先将请求封装成HttpEntityRequestCallback类对象,然后再处理请求。

1
2
3
4
5
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}

实际是把请求数据放在了一个HttpEntity中。如果requestBodyHttpEntity类型,就直接转;否则,放在HttpEntitybody中,如下:

1
2
3
4
5
6
7
8
9
10
11
public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {
super(responseType);
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity)requestBody;
} else if (requestBody != null) {
this.requestEntity = new HttpEntity(requestBody);
} else {
this.requestEntity = HttpEntity.EMPTY;
}

}

再看一下HttpEntity源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class HttpEntity<T> {
public static final HttpEntity<?> EMPTY = new HttpEntity();
private final HttpHeaders headers;
@Nullable
private final T body;

public HttpEntity(T body) {
this(body, (MultiValueMap)null);
}

public HttpEntity(MultiValueMap<String, String> headers) {
this((Object)null, headers);
}

再看一下HttpHeaders的源码:

1
public class HttpHeaders implements MultiValueMap<String, String>, Serializable {

简略了下代码,从代码已经可以看出,post请求是放在一个HttpEntity类型(headerMultiValueMap类型,body为泛型)的body中。

解决方案

1
2
3
4
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
HttpHeaders headers = new HttpHeaders();
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(paramMap, headers);
ResponseEntity<String> response = template.postForEntity(url, httpEntity, String.class);

改成MultiValueMap封装参数即可解决问题。

最后更新: 2019年07月27日 17:02

原始链接: http://blog.minhow.com/articles/java/restTemplate-post/

× 请我吃糖~
打赏二维码