描述

一般在企业级项目中,总会存在调用第三方接口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异常");
            }
        }
    }
}