公司屎山代码的缘故,里面使用的是RestTemplate,没办法,拿来用吧,结果悲剧了.
1.在使用Spring的RestTemplate进行文件上传的时候包下面的错误,好难找原因,又是Stack Overflow给了启发,其实这个RestTemplate好像不太好上传,因为我是除了文件还有别的参数
Could not write JSON: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer
废了好大的力气也没搞定,最后,换请求方式 解决,使用apache的HttpPost,核心代码如下:
2.使用RestTemplate时候,
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [application/x-www-form-urlencoded;charset=UTF-8]
post方法使用了MultiValueMap来封装参数,但是无法找到合适的类型转换,仔细查看我的RestTemplate对象获取方式是如下的:
public static RestTemplate getInstance(String charset) {
StringHttpMessageConverter m = new StringHttpMessageConverter(Charset.forName(charset));
RestTemplate restTemplate = new RestTemplateBuilder().additionalMessageConverters(m).build();
return restTemplate;
}
我是直接@Autowired注入的RestTemplate对象
使用了RestTemplateBuilder来创建RestTemplate对象,该方式只会为restTemplate模板初始化一个HttpMessageConverter(注:StringHttpMessageConverter间接实现HttpMessageConverter接口)
直接new的话会多几个Converter
3.Springboot使用RestTemplate发送Post请求postForEntity (application/json)时会出现的问题 (1).POST传递参数 :采用 LinkedMultiValueMap ,不能使用HashMap
String url = 'http://posturl';
MultiValueMap map= new LinkedMultiValueMap();
map.add("shopid","1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity> request = new HttpEntity>(map, headers);
return restTemplate.postForEntity(url, request,String.class);
注意 上面的请求支持参数类型均为String类型,如果MultiValueMap LinkedMultiValueMap 会将value放进list中,key --> [value] (2).采用JSONObject或者实体类传递参数
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
JSONObject param = new JSONObject();
param.put("username", "123");
HttpEntity formEntity = new HttpEntity(param, headers);
String result = restTemplate.postForObject(url, formEntity, String.class);
使用这种方式可以传递任意类型的参数,避免上面的情况
附源码:
public class LinkedMultiValueMap implements MultiValueMap, Serializable, Cloneable {
private static final long serialVersionUID = 3801124242820219131L;
private final Map> targetMap;
public LinkedMultiValueMap() {
this.targetMap = new LinkedHashMap();
}
public LinkedMultiValueMap(int initialCapacity) {
this.targetMap = new LinkedHashMap(initialCapacity);
}
public LinkedMultiValueMap(Map> otherMap) {
this.targetMap = new LinkedHashMap(otherMap);
}
@Nullable
public V getFirst(K key) {
List values = (List)this.targetMap.get(key);
return values != null && !values.isEmpty() ? values.get(0) : null;
}
public void add(K key, @Nullable V value) {
List values = (List)this.targetMap.computeIfAbsent(key, (k) -> {
return new LinkedList();
});
values.add(value);
}
public void addAll(K key, List values) {
List currentValues = (List)this.targetMap.computeIfAbsent(key, (k) -> {
return new LinkedList();
});
currentValues.addAll(values);
}
public void addAll(MultiValueMap values) {
Iterator var2 = values.entrySet().iterator();
while(var2.hasNext()) {
Entry> entry = (Entry)var2.next();
this.addAll(entry.getKey(), (List)entry.getValue());
}
}
public void set(K key, @Nullable V value) {
List values = new LinkedList();
values.add(value);
this.targetMap.put(key, values);
}
public void setAll(Map values) {
values.forEach(this::set);
}
public Map toSingleValueMap() {
LinkedHashMap singleValueMap = new LinkedHashMap(this.targetMap.size());
this.targetMap.forEach((key, values) -> {
if (values != null && !values.isEmpty()) {
singleValueMap.put(key, values.get(0));
}
});
return singleValueMap;
}