使用RestTemplate时候出现的小问题

1,041 阅读2分钟

公司屎山代码的缘故,里面使用的是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

image.png

废了好大的力气也没搞定,最后,换请求方式 解决,使用apache的HttpPost,核心代码如下:

image.png

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

image.png

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;

    }