package com.nanjing.water.common.util; import com.nanjing.water.common.enums.EHttpContentType; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; 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.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.ByteArrayBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; /** * Http请求工具类 * @author xiangyuanzhang * @date 2018-12-25 */ public final class HttpUtil { //region 常量 static final String STR_LOGTITLE = "SendHttpRequest"; static final String STR_UTF8 = "utf-8"; private static final int CONNECTTIMEOUT=20000; //endregion private HttpUtil() { throw new IllegalStateException("Utility class"); } static Boolean isLogRequestContent(EHttpContentType contentType) { Boolean isLog; switch (contentType) { case JSON: case XML: case FORM: isLog = Boolean.TRUE; break; default: isLog = Boolean.FALSE; break; } return isLog; } /** * 获取HttpPost对象 * @param url 请求url * @param contentType 请求类型(EHttpContentType),默认application/x-www-Form-urlencoded * @param headers 自定义请求头 * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) * @return */ private static HttpPost getHttpPost(String url, String contentType, Map headers, String proxy) { if(StringUtil.isNullOrEmpty(contentType)) { contentType = EHttpContentType.FORM.getDesc(); } HttpHost httpProxy = null; if(StringUtil.isNotNullOrEmpty(proxy)) { proxy = proxy.replace("https://", "").replace("http://", ""); String[] arrProxy = StringUtil.split(proxy, ":"); httpProxy = new HttpHost(arrProxy[0], Integer.valueOf(arrProxy[1])); } //创建httpPost HttpPost httpPost = new HttpPost(url); if(!EHttpContentType.FORMDATA.getDesc().equals(contentType)) { httpPost.setHeader("Content-Type", contentType); } RequestConfig config = RequestConfig.custom() //连接超时 .setConnectionRequestTimeout(Integer.parseInt("60000"))//60 * 1000 //请求超时 .setConnectTimeout(Integer.parseInt("300000"))//5 * 60 * 1000 //读取超时 .setSocketTimeout(Integer.parseInt("10000"))//10 * 1000 .setProxy(httpProxy) .build(); httpPost.setConfig(config); if(headers!=null && !headers.isEmpty()) { for (Map.Entry item : headers.entrySet()) { httpPost.setHeader(item.getKey(), item.getValue()); } } return httpPost; } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 * @param headers 自定义header * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) */ public static String doPost(String url, HttpEntity postData, EHttpContentType contentType, Map headers, String proxy) throws IOException { String responseContent; CloseableHttpClient httpclient = HttpClients.custom() .build(); HttpPost httpPost = HttpUtil.getHttpPost(url, contentType.getDesc(), headers, proxy); httpPost.setEntity(postData); CloseableHttpResponse response = null; Map logTags = new HashMap<>(); logTags.put("url", url.toLowerCase()); StringBuilder sbLog = new StringBuilder(HttpUtil.createLog(url, httpPost, contentType, postData)); try { response = httpclient.execute(httpPost); sbLog.append(String.format("ResponseTime:%s%n", CalendarUtil.toNowDateTimeMSStr())); StatusLine status = response.getStatusLine(); int state = status.getStatusCode(); if (state == HttpStatus.SC_OK) { HttpEntity responseEntity = response.getEntity(); responseContent = EntityUtils.toString(responseEntity); sbLog.append(String.format("ResponseData:%s%n", responseContent)); sbLog.append(String.format("ResponseDataReadedTime:%s%n", CalendarUtil.toNowDateTimeMSStr())); } else{ throw new RuntimeException(url+", the response “HttpStatus” of remote is :"+ state); } } catch (Exception e) { sbLog.append(String.format("the time at exception happend:%s%n", LocalDateTimeUtil.nowTimeStampStr())); //TODO log throw e; } finally { if (response != null) { try { response.close(); } catch (IOException e) { //TODO log } } try { httpclient.close(); } catch (IOException e) { //TODO log } } //TODO log return responseContent; } static String createLog(String url, HttpPost httpPost, EHttpContentType contentType, HttpEntity postData) { StringBuilder sbLog = new StringBuilder(); sbLog.append(String.format("url:%s%n", url)); sbLog.append(String.format("Request time:%s%n", CalendarUtil.toNowDateTimeMSStr())); sbLog.append(String.format("Request method:%s%n", httpPost.getMethod())); sbLog.append(String.format("ContentType:%s%n", httpPost.getEntity().getContentType())); HttpHost hProxy = httpPost.getConfig().getProxy(); if(hProxy!=null && StringUtil.isNotNullOrEmpty(hProxy.getHostName())) { sbLog.append(String.format("used http proxy:%s://%s:%s%n", hProxy.getSchemeName(), hProxy.getHostName(), hProxy.getPort())); } if(null!= httpPost.getAllHeaders() && httpPost.getAllHeaders().length>0) { sbLog.append(String.format("headers:%s%n", SerializeUtil.toJson(httpPost.getAllHeaders()))); } if(isLogRequestContent(contentType)) { try { sbLog.append(String.format("Request body:%s%n", EntityUtils.toString(postData, STR_UTF8))); } catch (Exception e) { // } } else { BigDecimal sizeKB = new BigDecimal(postData.getContentLength()).divide(new BigDecimal("1024")); sbLog.append(String.format("Request body:%s kb.%n", sizeKB.setScale(Integer.parseInt("2"), BigDecimal.ROUND_HALF_UP))); } sbLog.append(String.format("Request data readed time:%s%n", CalendarUtil.toNowDateTimeMSStr())); return sbLog.toString(); } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 */ public static String doPost(String url, byte[] postData, EHttpContentType contentType) throws IOException { return HttpUtil.doPost(url, postData, contentType, null, null); } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 * @param headers 自定义header * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) */ public static String doPost(String url, byte[] postData, EHttpContentType contentType, Map headers, String proxy) throws IOException { HttpEntity entity = new ByteArrayEntity(postData, ContentType.create(contentType.getDesc())); return HttpUtil.doPost(url, entity, contentType, headers, proxy); } /** * 发起文件上传请求 * @param url 请求url * @param postData 数据包 * @param fileName 文件名 * @param fileContentType 文件类型 */ public static String postFile(String url, byte[] postData, String fileName, String fileContentType) throws IOException { return HttpUtil.postFile(url, postData, fileName, fileContentType, null, null); } /** * 发起文件上传请求 * @param url 请求url * @param postData 数据包 * @param fileName 文件名 * @param fileContentType 文件类型 * @param headers 自定义header * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) */ public static String postFile(String url, byte[] postData, String fileName, String fileContentType, Map headers, String proxy) throws IOException { MultipartEntityBuilder entity = MultipartEntityBuilder.create(); entity.addPart("file", new ByteArrayBody(postData, ContentType.create(fileContentType), fileName)); return HttpUtil.doPost(url, entity.build(), EHttpContentType.FORMDATA, headers, proxy); } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 */ public static String doPost(String url, String postData, EHttpContentType contentType, Map headers) throws IOException { HttpEntity entity = new StringEntity(postData, STR_UTF8); return HttpUtil.doPost(url, entity, contentType, headers, null); } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) */ public static String doPost(String url, String postData, EHttpContentType contentType, Map headers, String proxy) throws IOException { HttpEntity entity = new StringEntity(postData, STR_UTF8); return HttpUtil.doPost(url, entity, contentType, headers, proxy); } /** * 发起post请求 * @param url 请求url * @param postData 数据包 * @param contentType 请求类型 */ public static String doPost(String url, String postData, EHttpContentType contentType) throws IOException { return HttpUtil.doPost(url, postData, contentType, null); } /** * 以“application/json”方式发起post请求 * @param url 请求url * @param postData 数据包 * @param headers 自定义header */ public static String postJson(String url, Object postData, Map headers) throws IOException { String json = SerializeUtil.toJson(postData); HttpEntity entity = new StringEntity(json, STR_UTF8); return HttpUtil.doPost(url, entity, EHttpContentType.JSON, headers, null); } /** * 以“application/json”方式发起post请求 * @param url 请求url * @param postData 数据包 * @param type 反序列化类型 * @param headers 自定义header * @param 反序列化对象泛型 */ public static T postJson(String url, Object postData, Class type, Map headers) throws IOException { return HttpUtil.postJson(url, postData, type, headers, null); } /** * 以“application/json”方式发起post请求 * @param url 请求url * @param postData 数据包 * @param type 反序列化类型 * @param headers 自定义header * @param proxy http代理(例: http://ntproxy.qa.nt.ctripcorp.com:8080) * @param 反序列化对象泛型 */ public static T postJson(String url, Object postData, Class type, Map headers, String proxy) throws IOException { String json = SerializeUtil.toJson(postData); HttpEntity entity = new StringEntity(json, STR_UTF8); String response = doPost(url, entity, EHttpContentType.JSON, headers, proxy); T result; try { result = SerializeUtil.toObject(response, type); } catch (Exception e) { result = null; } return result; } /** * 从url获取响应流 * @param url 请求url */ public static byte[] getStreamByUrl(String url) { CloseableHttpClient httpclient = HttpClients.custom().setConnectionManagerShared(true).build(); HttpGet httpGet = new HttpGet(url); RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(CONNECTTIMEOUT).setConnectTimeout(CONNECTTIMEOUT).build();//设置请求和传输超时时间 httpGet.setConfig(requestConfig); CloseableHttpResponse response = null; try { response = httpclient.execute(httpGet); int statuscode = response.getStatusLine().getStatusCode(); if (statuscode == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); InputStream isStream = entity.getContent(); return HttpUtil.getBytesFromInputStream(isStream); } } catch (Exception e) { //TODO log } finally { if (response != null) { //TODO log } try { httpclient.close(); } catch (IOException e) { //TODO log } } return new byte[0]; } /** * 从输入流返回字节数组 * @param input 输入流 */ public static byte[] getBytesFromInputStream(InputStream input) { ByteArrayOutputStream output = new ByteArrayOutputStream(); try { byte[] buffer = new byte[1024]; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); } return output.toByteArray(); } catch (IOException e) { //TODO log return new byte[0]; } finally { try { output.close(); input.close(); } catch (IOException e) { //TODO log } } } /** * 发起get请求,读取返回流为字符串 * @param url 请求url * @param charset 读取返回流的字符集 */ public static String doGet(String url, String charset) throws UnsupportedEncodingException { byte[] result = HttpUtil.getStreamByUrl(url); try { return new String(result, charset); } catch (UnsupportedEncodingException e) { try { return new String(result, STR_UTF8); } catch (Exception ex) { throw e; } } } /** * 发起get请求,以“utf-8”字符集,读取返回流为字符串 * @param url 请求url */ public static String doGet(String url) { try { return HttpUtil.doGet(url, STR_UTF8); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e.getMessage()); } } /** * 从url获取响应流 * @param url 请求url * @param headers 自定义header * @param proxy 代理地址([http:// | https://]www.baidu.com:8080) */ public static byte[] getStream(String url, Map headers, String proxy) { String action = "getStreamByUrl"; Map logTags = new HashMap<>(); logTags.put("action", action); logTags.put("url", url); HttpHost httpProxy = null; if(StringUtil.isNotNullOrEmpty(proxy)) { proxy = proxy.replace("https://", "").replace("http://", ""); String[] arrProxy = StringUtil.split(proxy, ":"); httpProxy = new HttpHost(arrProxy[0], Integer.parseInt(arrProxy[1])); } CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManagerShared(true) .build(); HttpGet httpGet = new HttpGet(url); if(null!=headers) { for (Map.Entry entry : headers.entrySet()) { httpGet.setHeader(entry.getKey(), entry.getValue()); } } //设置请求和传输超时时间 RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(CONNECTTIMEOUT) .setConnectTimeout(CONNECTTIMEOUT) .setProxy(httpProxy) .build(); httpGet.setConfig(requestConfig); CloseableHttpResponse response = null; try { response = httpclient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); InputStream isStream = entity.getContent(); return HttpUtil.getBytesFromInputStream(isStream); } } catch (Exception e) { //TODO log } finally { if (response != null) { try { response.close(); } catch (IOException e) { //TODO log } } try { httpclient.close(); } catch (IOException e) { //TODO log } } return new byte[0]; } public static byte[] getStream(String url, Map headers) { return HttpUtil.getStream(url, headers, null); } }