文章目录
  1. 1. 配置RestTemplate
  2. 2. POST请求之表单提交
    1. 2.1. 设置请求头
    2. 2.2. 设置请求参数
    3. 2.3. 发送请求
    4. 2.4. 解析返回参
    5. 2.5. 反序列化响应体为业务参数
  3. 3. POST请求之发送json
    1. 3.1. 设置请求头
    2. 3.2. 发送请求
    3. 3.3. 解析返回参数
  4. 4. 小结

笔者在两年前写过一篇RestTemplate使用相关的文章,地址: springboot中使用RestTemplate调用web服务小结

文章写作时SpringBoot版本尚在1.x徘徊,随着SpringBoot版本升级,有些用法在2.x版本中已经不适用。恰逢最近又用到了RestTemplate进行HTTP接口对接,
因此写作本文对最新的使用方法进行小结,方便后续参考,也希望能够帮到读者更好的使用RestTemplate在2.x的SpringBoot中进行HTTP接口的调用。

对于Get方式请求,2.x与1.x是兼容的,因此可以直接阅读上文中提到的链接,本文就不再重复赘述。

配置RestTemplate

首先需要配置RestTemplate,这是使用它的必要条件。

在项目中引入web依赖,maven坐标如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

只需要这个依赖即可。接着在项目中添加一个配置类,引入RestTemplate的bean定义,你可以直接引入下面的类。

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        /**读超时单位为ms*/
        factory.setReadTimeout(10000);
        /**连接超时单位为ms*/
        factory.setConnectTimeout(10000);
        return factory;
    }
}

这里,我指定读取超时时间和连接超时时间为10s,读者朋友可以根据自己的具体情况灵活配置。

POST请求之表单提交

使用POST请求方式最常见的就是表单提交,更加专业的说法就是:content-type为 application/x-www-form-urlencoded

使用RestTemplate请求 content-type为 application/x-www-form-urlencoded 格式的步骤如下:

设置请求头

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

在请求头中设置请求的content-type为application/x-www-form-urlencoded

设置请求参数

MultiValueMap<String, String> requestParam= new LinkedMultiValueMap<>();
requestParam.add("paramA", paramA);
requestParam.add("paramB", paramB);

这里通过MultiValueMap设置请求参数,如果用get方式展示的话,格式类似于paramA=paramA&paramB=paramB

发送请求

HttpEntity<MultiValueMap<String, String>> requestEntity =
        new HttpEntity<>(requestParam, headers);

ResponseEntity<String> responseEntity = restTemplate.exchange(
        requestUrl, HttpMethod.POST, requestEntity, String.class);
  1. 通过HttpEntity封装请求参数与headers
  2. 通过restTemplate.exchange方法发送请求,请求地址为requestUrl;请求方法为POST,请求参数为requestEntity,请求体数据格式为String

exchange的完整方法签名如下:

/**
 * Execute the HTTP method to the given URI template, writing the given request entity to the request, and
 * returns the response as {@link ResponseEntity}.
 * <p>URI Template variables are expanded using the given URI variables, if any.
 * @param url the URL
 * @param method the HTTP method (GET, POST, etc)
 * @param requestEntity the entity (headers and/or body) to write to the request
 * may be {@code null})
 * @param responseType the type of the return value
 * @param uriVariables the variables to expand in the template
 * @return the response as entity
 * @since 3.0.2
 */
<T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
        Class<T> responseType, Object... uriVariables) throws RestClientException;

我们直接引用注释的解释:

  1. 对给定的URI模板执行HTTP方法,将给定的请求实体写入请求,然后将响应返回为{@link ResponseEntity}。
  2. URI模板变量使用给定的URI变量(如果有的话)进行扩展
    1. url —请求地址网址
    2. method —HTTP方法(GET、POST等)
    3. requestEntity —要写入请求的实体(头和/或正文),可能是{@code null})
    4. responseType —返回值的类型
    5. uriVariables —要在模板中展开的变量
  3. 最终以实体形式返回响应

解析返回参

// 这是一段防御代码
if (responseEntity == null) {
    return null;
}

String checkResponseBody = responseEntity.getBody();

// 这是一段防御代码
if (StringUtils.isBlank(checkResponseBody)) {
    return null;
}

通过responseEntity.getBody() 获取响应体。

反序列化响应体为业务参数

通过上一步的代码,我们已经能够从响应中获取到responseBody。

接着就可以使用自己喜欢的方式将其反序列化为对象。我习惯使用jackson。

一段简单的反序列化代码如下:

JsonNode responseNode = OBJECT_MAPPER.readTree(checkResponseBody);
String status = responseNode.get("paramA").asText();
String msg = responseNode.get("paramB").asText();

这里解析出来的结果用json方式展示就是如下的样式:

{
    "paramA" : "paramA_value",
    "paramB" : "paramB_value",
}

POST请求之发送json

除了上述的常见方式(表单提交)外,当前有些较为前卫的单位热衷于在请求阶段也发送json格式的数据,

相当于直接提交一个json文档。服务端需要对该json文档进行解析,从而完成一定的工作。

json格式的content-type为 application/json

这里直接引用之前笔者写的开源秒杀案例中的代码进行讲解。

设置请求头

// 构造要序列化为json的业务对象
QueryOrdersResponse queryOrdersResponse = new QueryOrdersResponse();
queryOrdersRequest.setSign(sign);
ObjectMapper objectMapper = new ObjectMapper();

// 组装请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);

// 构造请求体
HttpEntity<QueryOrdersRequest> httpEntity = new HttpEntity<>(queryOrdersRequest, headers);
  1. 构造待发送的业务实体,为其设置属性
  2. 组装请求头,设置content-type为 application/json
  3. 初始化HttpEntity, 通过有参构造方法设置业务实体与headers】

发送请求

// 2.发送请求
ResponseEntity<String> responseEntity = null;

// 2.1 发起请求
responseEntity = restTemplate.postForEntity(queryOrdersUrl, httpEntity, String.class);
System.out.println("----" + JSON.toJSONString(responseEntity));

json格式的请求可以直接通过restTemplate.postForEntity发送,它的完整方法签名如下

<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType,
    Object... uriVariables) throws RestClientException;

解析返回参数

接收到ResponseEntity之后,通过 responseEntity.getBody();获取到responseBody,解析方式就和上文中提到的一致了。

我们可以使用jackson/gson(笔者就不推荐用fastJson了,因为众人皆知的原因,八阿哥有点多啊……)来进行解析了。

// 2.2. 解析返回参数
String responseBody = responseEntity.getBody();
queryOrdersResponse = objectMapper.readValue(responseBody, QueryOrdersResponse.class);
LOGGER.info("解析订单状态查询接口出参:[{}]", queryOrdersResponse.toString());

到此我们就实现了通过RestTemplate发送JSON格式的POST请求。

小结

本文偏应用实战,重点讲解了SpringBoot2.x版本中整合RestTemplate,并使用POST方法发送 application/x-www-form-urlencodedapplication/json 两种超媒体文本的步骤。

方便自己以后能够快速落地,并希望能够对读者有所帮助。

相关原理解析会在未来的文章中发布,敬请期待。



版权声明:

原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。

文章目录
  1. 1. 配置RestTemplate
  2. 2. POST请求之表单提交
    1. 2.1. 设置请求头
    2. 2.2. 设置请求参数
    3. 2.3. 发送请求
    4. 2.4. 解析返回参
    5. 2.5. 反序列化响应体为业务参数
  3. 3. POST请求之发送json
    1. 3.1. 设置请求头
    2. 3.2. 发送请求
    3. 3.3. 解析返回参数
  4. 4. 小结
Fork me on GitHub