再谈RestTemplate实战应用

笔者在两年前写过一篇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 两种超媒体文本的步骤。 方便自己以后能够快速落地,并希望能够对读者有所帮助。 相关原理解析会在未来的文章中发布,敬请期待。  
正文到此结束
Loading...