如何调第三方接口请求数据
描述
一般在企业级项目中,总会存在调用第三方接口API进行拉取和推送数据,这样就需要封装请求方法进行请求,常见的请求方式如下(可以根据需要进行修改代码,接口验证逻辑跟调用三方接口差不多,免费API调用https://api.gmit.vip/)。接口返回实体可以自行进行定义,根据业务要求的状态码进行处理返回的实体即可。除了以下三种方式,还有OKhttp、SpringBoot-RestTemplate可用于请求三方接口
调用三方接口的方式
方式一:JDK HttpURLConnection调用第三方接口
HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求
<!--日志打印依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.24</version>
</dependency>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @describe JDK HttpURLConnection调用第三方http接口
*/
public class HttpURLConnectionUtils {
private static final Logger log = LoggerFactory.getLogger(HttpURLConnectionUtils.class);
/**
* 发送get请求。支持Restful风格、参数拼接URL,并提供请求参数拼接功能
* @param httpUrl 请求URL
* @param header 请求头字段信息
* @param data 请求数据
* @param timeout 请求超时时间设置,单位毫秒。默认30s
* @return result 返回请求结果
*/
public static String doGet(String httpUrl,Map<String,String> header,Map<String,Object> data,int timeout){
HttpURLConnection connect = null;
//返回请求结果
StringBuilder result = new StringBuilder();
try {
if (Objects.nonNull(data) && data.size() > 0) {
//构造请求参数
StringBuilder paramBuilder = new StringBuilder();
paramBuilder.append(httpUrl).append("?");
Set<Map.Entry<String, Object>> entries = data.entrySet();
for (Map.Entry<String, Object> entry : entries) {
paramBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
httpUrl = paramBuilder.substring(0,paramBuilder.length() - 1);
}
//构造访问地址的URL
URL url = new URL(httpUrl);
//获取网络访问对象
connect = (HttpURLConnection)url.openConnection();
//设置请求参数:请求方式、请求过期时间、是否允许写入和读入、是否使用缓存、是否自动执行HTTP重定向
connect.setRequestMethod("GET");
connect.setConnectTimeout(timeout <=0 ? 30000 : timeout);
//connect.setReadTimeout(timeout <=0 ? 30000 : timeout);
connect.setDoInput(true);
connect.setDoOutput(false);
connect.setUseCaches(false);
connect.setInstanceFollowRedirects(true);
//设置请求头,比如Content-Type、accept等
if (!Objects.isNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entrySet = header.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
connect.setRequestProperty(entry.getKey(),entry.getValue());
}
}
//连接请求
connect.connect();
//获取返回结果
if (connect.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connect.getInputStream(),StandardCharsets.UTF_8));
String lines = null;
while ((lines = reader.readLine()) != null) {
result.append(lines);
}
} else {
return result.append("请求失败").toString();
}
} catch (IOException e) {
log.error("发送get请求错误,请求URL:{},请求参数:{},错误信息:{}",httpUrl,data,e.getMessage());
} finally {
if (!Objects.isNull(connect)) {
connect.disconnect();
}
}
return result.toString();
}
/**
* 发送post请求。必须通过header参数设置Content-Type类型
* @param httpUrl 请求url
* @param header 请求头设置
* @param data 请求数据
* @param timeout 请求超时时间
* @return result 请求结果
*/
public static String doPost(String httpUrl,Map<String,String> header,String data,int timeout){
HttpURLConnection connection = null;
BufferedWriter writer = null;
BufferedReader reader = null;
//返回请求结果
StringBuilder result = new StringBuilder();
try {
//构造访问地址的URL
URL url = new URL(httpUrl);
//获取网络访问对象
connection = (HttpURLConnection)url.openConnection();
//设置请求参数:请求方式、请求过期时间、是否允许写入和读入、请求参数为JSON
connection.setRequestMethod("POST");
connection.setConnectTimeout(timeout <=0 ? 30000 : timeout);
connection.setDoInput(true);
connection.setDoOutput(true);
//connection.setRequestProperty("Content-Type","application/json;charset=UTF-8");
//设置请求头,比如Content-Type、accept等
if (!Objects.isNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entries = header.entrySet();
for (Map.Entry<String, String> entry : entries) {
connection.setRequestProperty(entry.getKey(),entry.getValue());
}
}
//获取HttpURLConnection对象对应的输出流,进行请求接口
writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8));
writer.write(data);
writer.flush();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
//获取HttpURLConnection对象对应的输入流,获取返回结果
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String lines = null;
while ((lines = reader.readLine()) != null) {
result.append(lines);
}
} else {
result.append("请求失败");
}
} catch (IOException e) {
log.error("发送post请求错误,请求URL:{},请求参数:{},错误信息:{}",httpUrl,data,e.getMessage());
} finally {
//释放链接
releaseConnection(reader,writer,connection);
}
return result.toString();
}
/**
* 释放链接
* @param reader 读取流
* @param writer 写出流
* @param connection 连接
*/
public static void releaseConnection(BufferedReader reader,BufferedWriter writer,HttpURLConnection connection) {
if (!Objects.isNull(reader)) {
try {
reader.close();
} catch (IOException e) {
log.error("关闭读取流异常");
}
}
if (!Objects.isNull(writer)) {
try {
writer.close();
} catch (IOException e) {
log.error("关闭写出流异常");
}
}
if (!Objects.isNull(connection)) {
connection.disconnect();
}
}
}
方式二:通过 HttpClient 调用第三方接口
<!--HttpClient-->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @describe 通过HttpClient调用第三接口
*/
public class HttpClientUtils {
private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class);
/**
* 发送get请求。
* @param httpUrl 请求url
* @param data 请求参数
* @param timeout 请求超时时间
* @return 请求结果
*/
public static String doGet(String httpUrl,Map<String,String> header, Map<String,Object> data,int timeout){
String response = "";
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
GetMethod getMethod = null;
try {
//创建HttpClient并设置链接超时时间
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout <= 0 ? 30000 : timeout);
//拼接请求参数
if (Objects.nonNull(data) && data.size() > 0) {
StringBuilder param = new StringBuilder();
param.append(httpUrl).append("?");
Set<Map.Entry<String, Object>> entries = data.entrySet();
for (Map.Entry<String, Object> entry : entries) {
param.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
httpUrl = param.substring(0,param.length() - 1);
}
//创建GetMethod对象并设置请求头、请求超时时间、请求重试处理(默认请求三次)
getMethod = new GetMethod(httpUrl);
if (Objects.nonNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entries = header.entrySet();
for (Map.Entry<String, String> entry : entries) {
getMethod.addRequestHeader(entry.getKey(),entry.getValue());
}
}
getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,timeout <= 0 ? 30000 : timeout);
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
//执行HTTP GET请求获取响应状态码、响应内容
int statusCode = client.executeMethod(getMethod);
if (statusCode == HttpStatus.SC_OK) {
response = new String(getMethod.getResponseBody(), StandardCharsets.UTF_8);
//返回数据量大时使用以下方法,比如图片视频等
/*inputStream = new BufferedInputStream(getMethod.getResponseBodyAsStream());
outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get("E:\\project\\tms\\1.png")));
IOUtils.copy(inputStream,outputStream);
outputStream.flush();*/
} else {
log.warn("请求接口失败,请求参数:{},返回状态码为:{}",data,statusCode);
response = "请求接口失败" + new String(getMethod.getResponseBody(), StandardCharsets.UTF_8);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
releaseConnection(getMethod,inputStream,outputStream);
}
return response;
}
/**
* 发送post请求。
* @param httpUrl 请求url
* @param data 请求参数
* @param timeout 请求超时时间
* @return 请求结果
*/
public static String doPost(String httpUrl,Map<String,String> header, String data,int timeout){
String response = "";
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
PostMethod postMethod = null;
try {
//创建HttpClient并设置链接超时时间
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout <= 0 ? 30000 : timeout);
//创建GetMethod对象并设置请求超时时间、请求重试处理(默认请求三次)
postMethod = new PostMethod(httpUrl);
if (Objects.nonNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entries = header.entrySet();
for (Map.Entry<String, String> entry : entries) {
postMethod.addRequestHeader(entry.getKey(),entry.getValue());
}
}
postMethod.addRequestHeader("accept", "*/*");
postMethod.addRequestHeader("connection", "Keep-Alive");
//设置json格式传送
//postMethod.addRequestHeader("Content-Type", "application/json;charset=UTF-8");
//设置表单格式传送
postMethod.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
//添加请求参数,表单形式提交
//postMethod.addParameter("format", data);
//postMethod.addParameter("tel", data);
//添加请求参数,json形式提交
postMethod.setRequestBody(data);
//执行HTTP GET请求获取响应状态码、响应内容
int statusCode = client.executeMethod(postMethod);
if (statusCode == HttpStatus.SC_OK) {
response = new String(postMethod.getResponseBody(), StandardCharsets.UTF_8);
//返回数据量大时使用以下方法,比如图片视频等
/*inputStream = new BufferedInputStream(postMethod.getResponseBodyAsStream());
outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get("E:\\project\\tms\\1.png")));
IOUtils.copy(inputStream,outputStream);
outputStream.flush();*/
} else {
log.warn("请求接口失败,请求参数:{},返回状态码为:{}",data,statusCode);
response = "请求接口失败" + new String(postMethod.getResponseBody(), StandardCharsets.UTF_8);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
releaseConnection(postMethod,inputStream,outputStream);
}
return response;
}
/**
* 释放链接
* @param httpMethod 请求方式
* @param inputStream 输入流
* @param outputStream 输出流
*/
public static void releaseConnection(HttpMethodBase httpMethod, BufferedInputStream inputStream, BufferedOutputStream outputStream){
if (Objects.nonNull(httpMethod)) {
//释放链接
httpMethod.releaseConnection();
}
if (Objects.nonNull(outputStream)) {
try {
outputStream.close();
} catch (IOException e) {
log.error("关闭输出流异常,error: {}",e.getMessage());
}
}
if (Objects.nonNull(inputStream)) {
try {
inputStream.close();
} catch (IOException e) {
log.error("关闭输入流异常,error: {}",e.getMessage());
}
}
}
}
方式三:通过 CloseableHttpClient 调用第三方接口
<!--CloseableHttpClient-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @describe 通过CloseableHttpClient调用第三接口
*/
public class CloseableHttpClientUtils {
private static final Logger log = LoggerFactory.getLogger(CloseableHttpClientUtils.class);
/**
* 发送get请求。支持Restful风格、参数拼接URL
*
* @param httpUrl 请求url,支持Restful风格、参数拼接URL
* @param header 请求头设置
* @param data 请求参数,可传 null 或 空集合
* @param timeout 请求超时时间(单位毫秒),默认30s
* @return 请求结果
*/
public static String doGet(String httpUrl, Map<String, String> header, Map<String, Object> data, int timeout) {
org.apache.http.impl.client.CloseableHttpClient client = null;
CloseableHttpResponse response = null;
String result = null;
try {
//创建可关闭的 HttpClient 实例
client = HttpClients.createDefault();
//拼接请求参数
if (Objects.nonNull(data) && data.size() > 0) {
StringBuilder param = new StringBuilder();
param.append(httpUrl).append("?");
Set<Map.Entry<String, Object>> entrySet = data.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
param.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
httpUrl = param.substring(0, param.length() - 1);
}
//创建 HttpGet 实例并设置请求头
HttpGet httpGet = new HttpGet(httpUrl);
if (Objects.nonNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entries = header.entrySet();
for (Map.Entry<String, String> entry : entries) {
httpGet.setHeader(entry.getKey(), entry.getValue());
}
}
//请求配置项
RequestConfig config = RequestConfig.custom()
//设置连接超时时间
.setConnectTimeout(timeout <= 0 ? 30000 : timeout)
//设置传输超时时间
.setSocketTimeout(timeout <= 0 ? 30000 : timeout)
.build();
httpGet.setConfig(config);
//执行请求
response = client.execute(httpGet);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
} catch (IOException e) {
log.error("发送get请求错误,请求URL:{},错误信息:{}", httpUrl, e.getMessage());
} finally {
//释放链接
releaseConnection(client, response);
}
return result;
}
/**
* 发送post请求
*
* @param httpUrl 请求url
* @param header 请求头设置
* @param data 请求数据
* @param timeout 请求超时时间
* @return 请求结果
*/
public static String doPost(String httpUrl, Map<String, String> header, Map<String, Object> data, int timeout) {
CloseableHttpClient client = null;
CloseableHttpResponse response = null;
String result = null;
try {
//创建可关闭的 HttpClient 实例
client = HttpClients.createDefault();
//创建 HttpPost 实例并设置请求头
HttpPost httpPost = new HttpPost(httpUrl);
//以json形式提交请求
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
if (Objects.nonNull(header) && header.size() > 0) {
Set<Map.Entry<String, String>> entries = header.entrySet();
for (Map.Entry<String, String> entry : entries) {
httpPost.setHeader(entry.getKey(), entry.getValue());
}
}
//设置请求参数和参数格式
StringEntity entity = new StringEntity(JSONObject.toJSONString(data));
entity.setContentType("application/json;charset=UTF-8");
httpPost.setEntity(entity);
//请求配置项
RequestConfig config = RequestConfig.custom()
//设置连接超时时间
.setConnectTimeout(timeout <= 0 ? 30000 : timeout)
//设置传输超时时间
.setSocketTimeout(timeout <= 0 ? 30000 : timeout)
.build();
httpPost.setConfig(config);
//执行请求
response = client.execute(httpPost);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
} catch (IOException e) {
log.error("发送post请求错误,请求URL:{},请求参数:{},错误信息:{}", httpUrl, data, e.getMessage());
} finally {
//释放链接
releaseConnection(client, response);
}
return result;
}
/**
* 释放链接
* @param client 请求方式
* @param response 响应
*/
public static void releaseConnection(CloseableHttpClient client, CloseableHttpResponse response) {
if (Objects.nonNull(response)) {
try {
response.close();
} catch (IOException e) {
log.error("关闭CloseableHttpResponse异常");
}
}
if (Objects.nonNull(client)) {
try {
client.close();
} catch (IOException e) {
log.error("关闭CloseableHttpClient异常");
}
}
}
}