基於OkHttp網路通訊工具類(傳送get、post請求、檔案上傳和下載)
阿新 • • 發佈:2018-11-28
一、為什麼要用OkHttp?
okhttp是專注於提升網路連線效率的http客戶端。
優點:
1、它能實現同一ip和埠的請求重用一個socket,這種方式能大大降低網路連線的時間,和每次請求都建立socket,再斷開socket的方式相比,降低了伺服器伺服器的壓力。
2、okhttp 對http和https都有良好的支援。
3、okhttp 不用擔心android版本變換的困擾。
4、成熟的網路請求解決方案,比HttpURLConnection更好用。
5、支援非同步傳送網路請求,響應可線上程處理。
二、其它的網路通訊框架:
1、HttpURLConnection:java.util包下的http客戶端,對網路請求的封裝沒有HttpClient那麼徹底,api使用起來比較簡單,易於擴充套件。
2、HttpClient:Apache的一個第三方網路框架,api眾多,用起來比較方便,實現比較穩定,但不易於擴充套件。
3、Volley:google推出的網路通訊框架,適合處理資料量小、通訊頻繁的網路操作,內部封裝了非同步執行緒,不適合大資料量的請求。
下面對OkHttp做了一個簡單的封裝,可用於傳送get、post請求(支援請求引數格式為鍵值對、json格式)、檔案上傳、檔案下載。
import java.io.IOException; import java.nio.charset.Charset; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import com.alibaba.fastjson.JSONObject; import okhttp3.FormBody; import okhttp3.Headers; import okhttp3.HttpUrl; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class OkHttpUtils { private static final Logger LOGGER = LoggerFactory.getLogger(OkHttpUtils.class); public static final MediaType JSON = MediaType.get("application/json;charset=utf-8"); public static final MediaType OCTET_STREAM = MediaType.get("application/octet-stream"); /** * 請求帶的UA */ public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"; /** * 超時、讀、寫時長 */ public static final int TIMEOUT = 10; public static OkHttpClient getOkHttpClient() { return getOkHttpClient(TIMEOUT); } public static OkHttpClient getOkHttpClient(int timeout) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.readTimeout(TIMEOUT, TimeUnit.SECONDS); builder.writeTimeout(TIMEOUT, TimeUnit.SECONDS); builder.connectTimeout(TIMEOUT, TimeUnit.SECONDS); return builder.build(); } public static OkHttpResp sendGet(String url, Map<String, Object> reqHeaders, Map<String, Object> params) throws IOException { return sendGet(url, reqHeaders, params, TIMEOUT); } /** * get請求 * @param url 請求地址 * @param reqHeaders 請求頭 * @param params 請求引數 * @param timeout 超時時長 * @return * @throws IOException */ public static OkHttpResp sendGet(String url, Map<String, Object> reqHeaders, Map<String, Object> params, int timeout) throws IOException { if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("request url can not be null"); } OkHttpClient client = getOkHttpClient(timeout); HttpUrl.Builder urlBuilder = HttpUrl.get(url).newBuilder(); // 拼接引數 if (!CollectionUtils.isEmpty(params)) { for (Entry<String, Object> param : params.entrySet()) { Object value = param.getValue(); if (value == null) { urlBuilder.addEncodedQueryParameter(param.getKey(), null); } else { urlBuilder.addEncodedQueryParameter(param.getKey(), String.valueOf(param.getValue())); } } } HttpUrl httpUrl = urlBuilder.build(); Request.Builder reqBuilder = new Request.Builder().url(httpUrl).addHeader("User-Agent", USER_AGENT); // 增加請求頭 addHeaders(reqHeaders, reqBuilder); Request request = reqBuilder.get().build(); System.out.println(httpUrl.toString()); return getResponse(httpUrl.toString(), client, request); } public static OkHttpResp sendPostWithKeyValue(String url, Map<String, Object> headers, Map<String, Object> params) throws IOException { return sendPostWithKeyValue(url, headers, params, TIMEOUT); } /** * 傳送post請求,請求引數格式為鍵值對 * @param url 請求地址 * @param reqHeaders 請求頭 * @param params 請求引數 * @param timeout 超時時長 * @return * @throws IOException */ public static OkHttpResp sendPostWithKeyValue(String url, Map<String, Object> reqHeaders, Map<String, Object> params, int timeout) throws IOException { if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("request url can not be null"); } OkHttpClient client = getOkHttpClient(timeout); Request.Builder reqBuilder = new Request.Builder().url(url).addHeader("User-Agent", USER_AGENT); // 增加請求頭 addHeaders(reqHeaders, reqBuilder); FormBody.Builder formBuilder = new FormBody.Builder(Charset.forName("UTF-8")); FormBody formBody = formBuilder.build(); // 新增請求引數 if (!CollectionUtils.isEmpty(params)) { for (Map.Entry<String, Object> param : params.entrySet()) { Object obj = param.getValue(); if (obj != null) { formBuilder.add(param.getKey(), String.valueOf(param.getValue())); } else { formBuilder.add(param.getKey(), null); } } } Request request = reqBuilder.post(formBody).build(); return getResponse(url, client, request); } public static OkHttpResp sendPostWithJson(String url, Map<String, Object> reqHeaders, Map<String, Object> params) throws IOException { return sendPostWithJson(url, reqHeaders, params, TIMEOUT); } /** * 傳送post請求,請求引數格式為json格式 * @param url 請求地址 * @param reqHeaders 請求頭 * @param params 請求引數 * @param timeout 超時時長 * @return * @throws IOException */ public static OkHttpResp sendPostWithJson(String url, Map<String, Object> reqHeaders, Map<String, Object> params, int timeout) throws IOException { if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("request url can not be null"); } OkHttpClient client = getOkHttpClient(timeout); Request.Builder reqBuilder = new Request.Builder().url(url).addHeader("User-Agent", USER_AGENT); // 新增請求頭 addHeaders(reqHeaders, reqBuilder); // 新增請求引數 RequestBody requestBody = RequestBody.create(JSON, JSONObject.toJSONString(params)); if (CollectionUtils.isEmpty(params)) { requestBody = RequestBody.create(JSON, ""); } Request request = reqBuilder.post(requestBody).build(); return getResponse(url, client, request); } public static OkHttpResp uploadFile(String url, List<MultipartFile> files) throws IOException { return uploadFile(url, files, TIMEOUT); } /** * 上傳檔案 * @param url 請求地址 * @param files 檔案列表 * @param timeout 超時時長 * @return * @throws IOException */ public static OkHttpResp uploadFile(String url, List<MultipartFile> files, int timeout) throws IOException { if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("request url can not be null"); } OkHttpClient client = getOkHttpClient(timeout); MultipartBody.Builder multiBuilder = new MultipartBody.Builder(); multiBuilder.setType(MultipartBody.FORM); if (!CollectionUtils.isEmpty(files)) { for (MultipartFile multipartFile : files) { String fieldName = multipartFile.getFieldName(); String fileName = multipartFile.getFileName(); byte[] content = multipartFile.getContent(); multiBuilder.addFormDataPart(fieldName, fileName, RequestBody.create(OCTET_STREAM, content)); } } MultipartBody requestBody = multiBuilder.build(); Request request = new Request.Builder().url(url).addHeader("User-Agent", USER_AGENT).post(requestBody).build(); return getResponse(url, client, request); } public static byte[] downloadFile(String url) throws IOException { return downloadFile(url, TIMEOUT); } /** * 下載檔案 * @param url 請求地址 * @param timeout 超時時長 * @return * @throws IOException */ public static byte[] downloadFile(String url, int timeout) throws IOException { if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("request url can not be null"); } OkHttpClient client = getOkHttpClient(timeout); Request request = new Request.Builder().url(url).addHeader("User-Agent", USER_AGENT).get().build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { return null; } return response.body().bytes(); } catch (IOException e) { LOGGER.error("fail to establish the connection with " + url, e); throw e; } } private static OkHttpResp getResponse(String url, OkHttpClient client, Request request) throws IOException { // 確保Response和ResponseBody關閉 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { return null; } OkHttpResp resp = new OkHttpResp(); resp.setRespStr(response.body().string()); resp.setRespHeaders(response.headers()); return resp; } catch (IOException e) { LOGGER.error("fail to establish the connection with " + url, e); throw e; } } private static void addHeaders(Map<String, Object> reqHeaders, Request.Builder reqBuilder) { if (!CollectionUtils.isEmpty(reqHeaders)) { for (Entry<String, Object> reqHeader : reqHeaders.entrySet()) { Object value = reqHeader.getValue(); if (value != null) { reqBuilder.addHeader(reqHeader.getKey(), String.valueOf(reqHeader.getValue())); } else { reqBuilder.addHeader(reqHeader.getKey(), null); } } } } public static class MultipartFile { /** * 檔案域名,相當於表單中檔案域名 */ private String fieldName; /** * 檔名 */ private String fileName; /** * 檔案路徑 */ private byte[] content; public MultipartFile() { super(); } public MultipartFile(String fieldName, String fileName, byte[] content) { super(); this.fieldName = fieldName; this.fileName = fileName; this.content = content; } public String getFieldName() { return fieldName; } public void setFieldName(String fieldName) { this.fieldName = fieldName; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; } } public static class OkHttpResp { /** * 響應字串 */ private String respStr; /** * 響應頭 */ private Headers respHeaders; public String getRespStr() { return respStr; } public void setRespStr(String respStr) { this.respStr = respStr; } public Headers getRespHeaders() { return respHeaders; } public void setRespHeaders(Headers respHeaders) { this.respHeaders = respHeaders; } } }
對阿里FastJSONj進行JavaBean到json字串對映的簡單封裝。
import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.springframework.util.CollectionUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.serializer.SerializerFeature; public class JsonUtils { /** * 將物件轉換為json字串 * * @param obj * 轉換的物件 * @return */ public static String toJsonString(Object obj) { return toJsonString(obj, false); } /** * 物件轉換為json字串,可允許轉換空值 * * @param obj * 轉換的物件 * @param isNullValueAllowed * 是否允許空值 * @return */ public static String toJsonString(Object obj, boolean isNullValueAllowed) { if (obj == null) { return null; } if (!isNullValueAllowed) { return JSON.toJSONString(obj); } return JSON.toJSONString(obj, SerializerFeature.WRITE_MAP_NULL_FEATURES); } /** * 將json字串轉換為javaBean * * @param jsonStr * json字串 * @param clazz * 執行時物件 * @return */ public static <T> T toJavaBean(String jsonStr, Class<T> clazz) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseObject(jsonStr, clazz); } /** * 字串轉換為list * * @param jsonStr * json字串 * @param clazz * 執行時物件 * @return */ public static <T> List<T> toList(String jsonStr, Class<T> clazz) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseArray(jsonStr, clazz); } /** * 將json字串轉換為map * * @param jsonStr * json字串 * @return */ public static Map<String, Object> toMap(String jsonStr) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseObject(jsonStr, new TypeReference<Map<String, Object>>() { }); } /** * 將javaBean轉換為map * * @param obj * 轉換的物件 * @return */ public static Map<String, Object> javaBeanToMap(Object obj) { if (obj == null) { return null; } return toMap(toJsonString(obj)); } /** * 將map轉換為javaBean * * @param map * map例項 * @param clazz * 執行時物件 * @return */ public static <T> T mapToJavaBean(Map<String, ? extends Object> map, Class<T> clazz) { if (CollectionUtils.isEmpty(map)) { return null; } String jsonStr = JSON.toJSONString(map); return JSON.parseObject(jsonStr, clazz); } }