笔者在两年前写过一篇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¶mB=paramB
发送请求
HttpEntity<MultiValueMap<String, String>> requestEntity =
new HttpEntity<>(requestParam, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
requestUrl, HttpMethod.POST, requestEntity, String.class);
- 通过HttpEntity封装请求参数与headers
- 通过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;
我们直接引用注释的解释:
- 对给定的URI模板执行HTTP方法,将给定的请求实体写入请求,然后将响应返回为{@link ResponseEntity}。
- URI模板变量使用给定的URI变量(如果有的话)进行扩展
- url —请求地址网址
- method —HTTP方法(GET、POST等)
- requestEntity —要写入请求的实体(头和/或正文),可能是{@code null})
- responseType —返回值的类型
- uriVariables —要在模板中展开的变量
- 最终以实体形式返回响应
解析返回参
// 这是一段防御代码
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);
- 构造待发送的业务实体,为其设置属性
- 组装请求头,设置content-type为 application/json
- 初始化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-urlencoded
及
application/json
两种超媒体文本的步骤。
方便自己以后能够快速落地,并希望能够对读者有所帮助。
相关原理解析会在未来的文章中发布,敬请期待。