java中的远程调用http

分享一下项目中用过的远程调用方法并总结两种请求方式的差别

 http远程调用一般分为两种 get和post(其它方式暂不考虑)

pom包

<!--http远程调用-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
        </dependency>

 

get请求方式

/**
     * 发送get请求
     * authorization为请求token(不需要可以去掉)
     */
    public static String get(String url,String authorization) {
        String res;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Authorization", authorization);
            res = execute(httpClient, httpGet);
        } finally {
            doHttpClientClose(httpClient);
        }
        return res;
    }

    private static String execute(CloseableHttpClient httpClient, HttpUriRequest httpGetOrPost) {
        String res = null;
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGetOrPost);
            HttpEntity entity = response.getEntity();
            res = EntityUtils.toString(entity, CHARSET_UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            doResponseClose(response);
        }
        return res;
    }

    /**
     * httpClient关闭
     */
    private static void doHttpClientClose(CloseableHttpClient httpClient) {
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * response关闭
     */
    private static void doResponseClose(CloseableHttpResponse response) {
        if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

get我觉得通篇下来就是url比较重要,其它的都是一些常规方法,因为get方法基本是在url上拼参数

String url = "127.0.0.1:8080/api/personList?pageNum=1&pageSize=10&idcardNo="+idCard;

 

post请求方法

  post的请求方式就多种多样了 application/json、application/x-www-form-urlencoded、application/form-data

 

这里是一个post请求方法

//自定义的请求头也可以写死在调用方法里面
Map<String, String> headerParam = new HashMap<>(); headerParam.put("Accept", "*/*"); headerParam.put("Content-Type", "application/x-www-form-urlencoded");

//map是自己封装的参数  
/**   * 设置超时时间及重试次数   */   private static final int retryCount = 3;   private static final RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(15000) .setConnectTimeout(15000) .setConnectionRequestTimeout(15000) .build();   /** * 通用型httpPost调用 */ public static String post(final String url, Map<String, String> map, final Map<String, String> headParam) { final CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; int index = 0; final HttpPost httpPost = new HttpPost(url); try { //将头部header参数写进httpPost的header中 if (headParam != null) { for (final String key : headParam.keySet()) { httpPost.setHeader(key, headParam.get(key)); } } httpPost.setHeader("Authorization", "admin"); //将外部参数写进params中(这里也是一个个去写入,理论上application/form-data也是这种写入方式) List<NameValuePair> params = new ArrayList<>(); if(map!=null){ for (Map.Entry<String, String> entry : map.entrySet()) { params.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } } //设置参数到请求对象中 httpPost.setEntity(new UrlEncodedFormEntity(params, "utf-8")); httpPost.setConfig(requestConfig); response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { while(null == response && index < retryCount){ log.info("第 {} 次重试", index + 1); try { response = httpClient.execute(httpPost); } catch (Exception e1) { log.error("报错结果:", e1); } index++; } try { assert response != null; response.close(); } catch (IOException e2) { e2.printStackTrace(); } } finally { try { assert response != null; response.close(); } catch (IOException e3) { e3.printStackTrace(); } } return resultString; }

 

application/json其实只是换下写入参数的方法


//设置请求头
Map<String, String> headerParam = new HashMap<>();
headParam.addHeader("Content-Type", "application/json; charset=utf-8");
headParam.setHeader("Accept", "*/*");

//param是你自己封装的参数
   
/**
* 通用型httpPost调用
*/
public static String post(final String url, JSONObject param, final Map<String, String> headParam) {
final CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
int index = 0;
final HttpPost httpPost = new HttpPost(url);
try {
//将头部header参数写进httpPost的header中
if (headParam != null) {
for (final String key : headParam.keySet()) {
httpPost.setHeader(key, headParam.get(key));
}
}
httpPost.setHeader("Authorization", "admin");
//将整体参数变成json传进去(这里与上面方法会有区别)
if (EmptyUtils.isNotEmpty(param)) {
httpPost.setEntity(new StringEntity(param.toJSONString(), StandardCharsets.UTF_8));
}

httpPost.setConfig(requestConfig);
response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "utf-8");
}
catch (Exception e) {
while(null == response && index < retryCount){
log.info("第 {} 次重试", index + 1);
try {
response = httpClient.execute(httpPost);
} catch (Exception e1) {
log.error("报错结果:", e1);
}
index++;
}
try {
assert response != null;
response.close();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
finally {
try {
assert response != null;
response.close();
}
catch (IOException e3) {
e3.printStackTrace();
}
}
return resultString;
}

参数用JSONObject param传递感觉还是不太方便

得一个个写参数封装进param

JSONObject param = new JSONObject(); Map<String, Object> map = new HashMap<>(); map.put("name", "123"); map.put("phone", "1234"); param.put("params", map);

因为传参数我一般习惯用实体类传参(特别是参数比较多的情况)

用Object object传参,不管你传过来的参数是map还是JSONObject还是实体类

/**
     * 通用型httpPost调用
     */
    public static String post(final String url, final Object object, final Map<String, String> headParam) {
        final CloseableHttpClient httpClient =  HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        int index = 0;
        final HttpPost httpPost = new HttpPost(url);
        try {
            //将头部header参数写进httpPost的header中
            if (headParam != null) {
                for (final String key : headParam.keySet()) {
                    httpPost.setHeader(key, headParam.get(key));
                }
            }
            httpPost.setHeader("Authorization", "admin");

            //这里将传过来的object参数转成JSONObject(多了这一步)
            String json = JSONObject.toJSONString(object);
            JSONObject jsonObject = JSONObject.parseObject(json);
            
            //将整体参数变成json传进去
            if (EmptyUtils.isNotEmpty(object)) {
                httpPost.setEntity(new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8));
            }

            httpPost.setConfig(requestConfig);
            response = httpClient.execute(httpPost);

            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        }
        catch (Exception e) {
        //这里逻辑不用管,因为有设置超时时间和重试次数,不需要这里逻辑可忽略
while(null == response && index < retryCount){ log.info("第 {} 次重试", index + 1); try { response = httpClient.execute(httpPost); } catch (Exception e1) { log.error("报错结果:", e1); } index++; } try { assert response != null; response.close(); } catch (IOException e2) { e2.printStackTrace(); } } finally { try { assert response != null; response.close(); } catch (IOException e3) { e3.printStackTrace(); } } return resultString; }

关于get、post请求远程调用的就讲完了

还有一些调用遇到的例子也给大家分享下

忽略ssl证书警告(有些接口可能配置了https)

 

方法不可完全复制,如果需要,将忽略ssl证书警告方法放到上面方法稍微修改下

 static CloseableHttpClient httpClient;

    /**
     * 忽略ssl证书警告
     */
    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                // 信任所有
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    /**
     * 根据token查询接口
     */
    public static String doPost(final String url, final Object object, String token) {
        int index = 0;
        final CloseableHttpClient httpclient =  HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            //设置httpPost
            HttpPost httpPost = setHttpPost(url, object);
            httpPost.setHeader("Authorization", token);
            httpPost.setConfig(requestConfig);
            try {
          //主要是这里先调用忽略ssl证书的方法后才去调用远程接口 httpClient
= createSSLClientDefault(); response = httpClient.execute(httpPost); } catch (SocketTimeoutException e) { while(null == response && index < retryCount){ log.error("第 {} 次重试, url:{}", index + 1, url); try { response = httpclient.execute(httpPost); } catch (Exception e1) { log.error("第 {} 次重试结果, e:{}", index + 1, e1.getMessage()); } index++; log.info("SocketTimeoutException结果: e{}", e.getMessage()); } } //解析返回数据 assert response != null; resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } catch (Exception e) { log.info("Exception结果: url:{}, e:{}", url, e.getMessage()); //如果异常为自定义异常则主动抛出 if (e instanceof BizException) { try { throw e; } catch (IOException ex) { ex.printStackTrace(); } } closeResponse(response); } finally { closeResponse(response); } return resultString; }

 



 

posted @ 2024-04-09 21:22  马革皮  阅读(43)  评论(0编辑  收藏  举报