RestTemplate进行post请求调用需要注意的坑

1. 背景

        项目上需要写一个大屏批量、定时调用接口的websocket,为了方便,决定使用spring自带的RestTemplate来完成http请求。get请求时,没那么多需要注意的地方。但在post请求时出现了问题。

2. 遇到的问题

先来看一下post请求的代码实例

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        List<Object> idList = new ArrayList<>();
        idList.add("62d7d2d639b7566338080876");
        idList.add("6290584aad22ce2849baba5a");
        body.add("idList", idList);//问题出现在这个地方
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
        String reqUrl= "http://192.168.18.228:9999/ts-query/api/user/define/service/list";
        DataSet<?> platformResult = new RestTemplate().postForEntity(reqUrl, entity, DataSet.class).getBody();

跟踪代码发现

 查了一下MultiValueMap的说明发现了此问题出现的原因:

MultiValueMap同一个key下面可以放多个value

意思就是如果用add方法存放,会放到一个数组中,不会像普通map一样进行重复键覆盖的情况

所以就出现了上面截图出现的一个key中存放的居然是个数组中的数组,导致调用请求未正常返回

源码如下

	@Override
	public void add(K key, @Nullable V value) {
		List<V> values = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
		values.add(value);
	}

3. 解决方案

很简单,将有问题的代码修改为以下代码即可

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        List<Object> idList = new ArrayList<>();
        idList.add("62d7d2d639b7566338080876");
        idList.add("6290584aad22ce2849baba5a");
        body.put("idList", idList);// 将add修改为put即可
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
        String reqUrl= "http://192.168.18.228:9999/ts-query/api/user/define/service/list";
        DataSet<?> platformResult = new RestTemplate().postForEntity(reqUrl, entity, DataSet.class).getBody();

 当然,请求参数用add还是用put,需要根据业务需求来使用。put方法只允许存放List<Object>类型的参数,所以有一定的局限性。也可以将上面的代码修改为如下方式

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
//        List<Object> idList = new ArrayList<>();
//        idList.add("62d7d2d639b7566338080876");
//        idList.add("6290584aad22ce2849baba5a");
        body.add("idList", "62d7d2d639b7566338080876");
        body.add("idList", "6290584aad22ce2849baba5a");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
        String reqUrl= "http://192.168.18.228:9999/ts-query/api/user/define/service/list";
        DataSet<?> platformResult = new RestTemplate().postForEntity(reqUrl, entity, DataSet.class).getBody();

`RestTemplate` 是Spring框架提供的用于发送HTTP请求的同步客户端。它提供了多种便捷的方法来执行常见类型的HTTP请求,并且可以很容易地与Spring的声明式REST客户端(如`@RestClient`接口)集成。 要使用`RestTemplate`发送POST请求,你需要创建一个`RestTemplate`实例,然后使用`postForEntity`、`postForObject`或`exchange`等方法之一来发送请求。下面是使用`RestTemplate`发送POST请求的基本步骤: 1. 首先,你需要在项目中引入Spring Web依赖,这样才能使用`RestTemplate`。 2. 创建`RestTemplate`实例,这通常通过Spring的依赖注入来完成。 3. 准备HTTP请求体,通常是将要发送的数据封装在一个POJO对象中。 4. 调用`RestTemplate`的方法发送POST请求,并接收响应。 以下是一个简单的例子,展示了如何使用`RestTemplate`发送POST请求: ```java import org.springframework.web.client.RestTemplate; import org.springframework.http.HttpEntity; import org.springframework.http.ResponseEntity; import org.springframework.http.MediaType; import org.springframework.http.HttpHeaders; // 创建RestTemplate实例 RestTemplate restTemplate = new RestTemplate(); // 设置请求头,指定内容类型为application/json HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // 封装POST请求体 String jsonInputString = "{\"key1\":\"value1\", \"key2\":\"value2\"}"; HttpEntity<String> request = new HttpEntity<>(jsonInputString, headers); // 发送POST请求 ResponseEntity<String> response = restTemplate.postForEntity("http://example.com/api/resource", request, String.class); // 获取响应内容 String result = response.getBody(); ``` 上面的代码中,我们首先创建了一个`RestTemplate`实例。然后,我们设置了请求头,以指示我们希望发送JSON格式的数据。之后,我们创建了一个包含请求数据的`HttpEntity`对象。最后,我们调用`postForEntity`方法发送POST请求,并通过泛型参数`String.class`指定了期望响应体的类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值