背景:
在做项目的时候,遇到接口对接,需要把数据发送到对方的接口中,接到项目的时候一脸懵逼,我也没搞过这样的对接,只会增删改查,看了文档,是通过http发送给对方的,对方要json数据传输。
开工:
- 先测试是否能推送到对方的网址
强烈推荐大家使用postman测试接口,填写测试数据 - 根据文档看发送后返回的数据,如果报404那些状态码,根据状态码判断对方给的文档是否标准
- 利用RestTemplate发Http请求
英文不错的可以看看:
官方文档传送门 英文不太行的可以看看这个
文档传送门
RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。当然你也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp。
- 上代码
3.1 pom下载
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
3.2 RestTemplate配置
配置application.yml
http_pool:
max_total: 200
default_max_per_route: 100
connect_timeout: 5000
connection_request_timeout: 1000
socket_timeout: 65000
validate_after_inactivity: 2000
新建ApplicationValues.java
这个是读取配置中的参数方法
package com.ktamrinterface.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @description 获取Application配置数据
* @date
*/
@Component
public class ApplicationValues {
@Value("${http_pool.max_total}")
private int maxTotal;
@Value("${http_pool.default_max_per_route}")
private int maxPerRoute;
@Value("${http_pool.connect_timeout}")
private int connTimeOut;
@Value("${http_pool.connection_request_timeout}")
private int connReqTimeOut;
@Value("${http_pool.socket_timeout}")
private int socketTimeout;
@Value("${http_pool.validate_after_inactivity}")
private int inactivity;
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxPerRoute() {
return maxPerRoute;
}
public void setMaxPerRoute(int maxPerRoute) {
this.maxPerRoute = maxPerRoute;
}
public int getConnTimeOut() {
return connTimeOut;
}
public void setConnTimeOut(int connTimeOut) {
this.connTimeOut = connTimeOut;
}
public int getConnReqTimeOut() {
return connReqTimeOut;
}
public void setConnReqTimeOut(int connReqTimeOut) {
this.connReqTimeOut = connReqTimeOut;
}
public int getSocketTimeout() {
return socketTimeout;
}
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
public int getInactivity() {
return inactivity;
}
public void setInactivity(int inactivity) {
this.inactivity = inactivity;
}
}
新建RestTemplateConfig.java
这个是配置我们的底层http客户端(这里我们使用apache的client
如何配置:
Spring提供了HttpComponentsClientHttpRequestFactory可以通过该方法来配置我们的http客户端
package com.ktamrinterface.config;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* @description http工厂配置
* @date
*/
@Configuration
public class RestTemplateConfig {
@Autowired
private ApplicationValues appValues;
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(appValues.getMaxTotal());
connectionManager.setDefaultMaxPerRoute(appValues.getMaxPerRoute());
connectionManager.setValidateAfterInactivity(appValues.getInactivity());
RequestConfig requestConfig = RequestConfig.custom()
//服务器返回数据(response)的时间,超过抛出read timeout
.setSocketTimeout(appValues.getSocketTimeout())
//连接上服务器(握手成功)的时间,超出抛出connect timeout
.setConnectTimeout(appValues.getConnTimeOut())
//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(appValues.getConnReqTimeOut())
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
发送请求
RestTemplate对于不同的请求方式提供了不同的函数、我把官方的图贴一下、下面我会把常用的跟大家说一下图片传送门
package com.ktamrinterface.quartz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
public class TuiSongJob2 {
@Autowired
private RestTemplate restTemplate;
/**
* 生成post请求的JSON请求参数
*
* @param yinJiang 需要发送的json数据
* @return
*/
protected HttpEntity<Map> generatePostJson(Map<String, Object> yinJiang) {
//如果需要其它的请求头信息、都可以在这里追加
HttpHeaders httpHeaders = new HttpHeaders();
MediaType type = MediaType.parseMediaType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpHeaders.setContentType(type);
HttpEntity<Map> httpEntity = new HttpEntity<>(yinJiang, httpHeaders);
return httpEntity;
}
/**
* 生成get参数请求url
* 示例:https://0.0.0.0:80/api?u=u&o=o
* 示例:https://0.0.0.0:80/api
*
* @param protocol 请求协议 示例: http 或者 https
* @param uri 请求的uri 示例: 0.0.0.0:80
* @param yinJiang 请求参数
* @return
*/
public String generateRequestParameters(String protocol, String uri, Map<String, Object> yinJiang) {
StringBuilder sb = new StringBuilder(protocol).append("://").append(uri);
if (yinJiang!=null) {
sb.append("?");
for (Map.Entry map : yinJiang.entrySet()) {
sb.append(map.getKey())
.append("=")
.append(map.getValue())
.append("&");
}
uri = sb.substring(0, sb.length() - 1);
return uri;
}
return sb.toString();
}
/**
* post请求、请求参数为json
*
* @param yinJiang 需要发送的json数据
* @param sendUrl 填写对方的接口地址
* @return
*/
protected String sendPost(Map<String, Object> yinJiang, String sendUrl) {
String uri = sendUrl;
ResponseEntity<String> yinJiangResponseEntity = restTemplate.postForEntity
(
uri,
generatePostJson(yinJiang),
String.class
);
String body = yinJiangResponseEntity.getBody();
return body;
}
/**
* get请求、请求参数为?拼接形式的
* <p>
* 最终请求的URI如下:
* <p>
* http://127.0.0.1:80/?name=张耀烽&sex=男
*
* @return
*/
public String sendGet(String protocol, String uri, Map<String, Object> yinJiang) {
ResponseEntity responseEntity = restTemplate.getForEntity
(
generateRequestParameters(protocol, uri, yinJiang),
String.class
);
return (String) responseEntity.getBody();
}
}
- 调用
在发送完成之后对方会给我返回一个json结果,我要把这个json读取出来,我导入了一个json工具类
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
接下来就是调用了,我只是贴出部分主要代码
我要发送这样的格式的数据所以我就这样写
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> m2 = new HashMap<>();
for(int i = 1;i<=n;i++){
try {
//取出每n次的数据
list2 = list.stream().skip((i * uploadNumber) - uploadNumber).limit(uploadNumber).collect(Collectors.toList());
m2.put("cbyId",cbyId);
m2.put("cbyName",cbyName);
m2.put("cbyCode",cbyCode);
m2.put("sMon",sMon);
m2.put("records",list2);
//这里就调用上面的发送方法
String s = sendPost(m2, sendUrl);
//对返回后的json数据解析
mInfo = mapper.readValue(s, Map.class);
}catch (Exception e){
System.out.println("上传数据发生异常:"+e.getMessage()+",第"+i+"次失败");
break;
}
发送成功后的,对方返回的消息,结果展示如下
如果不成功欢迎大家留言,如果发现博文中发现有错误,欢迎各位老鸟多多指教一二。