一、为什么要用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格式)、文件上传、文件下载。
package com.universe.thirdparty.okhttp; import java.io.IOException; import java.nio.charset.Charset; import java.time.Duration; import java.util.List; import java.util.Map; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.alibaba.fastjson.JSONObject; import com.universe.thirdparty.fastjson.CollectionUtils; import okhttp3.FormBody; import okhttp3.Headers; import okhttp3.HttpUrl; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.OkHttpClient.Builder; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; public class OkHttpUtils { public static final MediaType JSON = MediaType.get("application/json;charset=utf-8"); public static final MediaType OCTET_STREAM = MediaType.get("application/octet-stream"); /** * 超时、读、写时长 */ private static final long TIMEOUT_MILLIS = 2000; private static final Builder DEFAULT_CLIENT_BUILDER = new OkHttpClient.Builder(); static { DEFAULT_CLIENT_BUILDER.readTimeout(Duration.ofMillis(TIMEOUT_MILLIS)); DEFAULT_CLIENT_BUILDER.writeTimeout(Duration.ofMillis(TIMEOUT_MILLIS)); DEFAULT_CLIENT_BUILDER.connectTimeout(Duration.ofMillis(TIMEOUT_MILLIS)); } public static OkHttpClient getOkHttpClient() { return DEFAULT_CLIENT_BUILDER.build(); } public static synchronized OkHttpClient getOkHttpClient(long timeoutInMillis) { DEFAULT_CLIENT_BUILDER.readTimeout(Duration.ofMillis(timeoutInMillis)); DEFAULT_CLIENT_BUILDER.writeTimeout(Duration.ofMillis(timeoutInMillis)); DEFAULT_CLIENT_BUILDER.connectTimeout(Duration.ofMillis(timeoutInMillis)); return DEFAULT_CLIENT_BUILDER.build(); } public static OkHttpResp sendGet(String url, Map<String, Object> reqHeaders, Map<String, Object> params) throws IOException { return sendGet(url, reqHeaders, params, TIMEOUT_MILLIS); } public static OkHttpResp sendGet(String url, Map<String, Object> reqHeaders, Map<String, Object> params, long timeoutInMillis) throws IOException { OkHttpClient client = getOkHttpClient(timeoutInMillis); HttpUrl.Builder urlBuilder = HttpUrl.get(url).newBuilder(); // 拼接参数 if (!CollectionUtils.isEmpty(params)) { params.forEach((key, value) -> { urlBuilder.addEncodedQueryParameter(key, String.valueOf(value)); }); } HttpUrl httpUrl = urlBuilder.build(); Request.Builder reqBuilder = new Request.Builder().url(httpUrl); addHeaders(reqHeaders, reqBuilder); Request request = reqBuilder.get().build(); return getResponse(client, request); } public static OkHttpResp sendPostInHtmlForm(String url, Map<String, Object> headers, Map<String, Object> params) throws IOException { return sendPostInHtmlForm(url, headers, params, TIMEOUT_MILLIS); } public static OkHttpResp sendPostInHtmlForm(String url, Map<String, Object> reqHeaders, Map<String, Object> params, long timeoutInMillis) throws IOException { OkHttpClient client = getOkHttpClient(timeoutInMillis); Request.Builder reqBuilder = new Request.Builder().url(url); addHeaders(reqHeaders, reqBuilder); FormBody.Builder formBuilder = new FormBody.Builder(Charset.forName("UTF-8")); FormBody formBody = formBuilder.build(); if (!CollectionUtils.isEmpty(params)) { params.forEach((paramName, paramValue) -> { formBuilder.add(paramName, String.valueOf(paramValue)); }); } Request request = reqBuilder.post(formBody).build(); return getResponse(client, request); } public static OkHttpResp sendPostInJsonFormat(String url, Map<String, Object> reqHeaders, Map<String, Object> params) throws IOException { return sendPostInJsonFormat(url, reqHeaders, params, TIMEOUT_MILLIS); } public static OkHttpResp sendPostInJsonFormat(String url, Map<String, Object> reqHeaders, Map<String, Object> params, long timeoutInMillis) throws IOException { OkHttpClient client = getOkHttpClient(timeoutInMillis); Request.Builder reqBuilder = new Request.Builder().url(url); addHeaders(reqHeaders, reqBuilder); RequestBody requestBody = RequestBody.create(JSON, JSONObject.toJSONString(params)); Request request = reqBuilder.post(requestBody).build(); return getResponse(client, request); } public static OkHttpResp uploadFile(String url, List<MultipartFile> files) throws IOException { return uploadFile(url, files, TIMEOUT_MILLIS); } public static OkHttpResp uploadFile(String url, List<MultipartFile> files, long timeoutInMillis) throws IOException { OkHttpClient client = getOkHttpClient(timeoutInMillis); MultipartBody.Builder multiBuilder = new MultipartBody.Builder(); multiBuilder.setType(MultipartBody.FORM); if (!CollectionUtils.isEmpty(files)) { files.forEach(multipartFile -> { 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).post(requestBody).build(); return getResponse(client, request); } public static byte[] downloadFile(String url) throws IOException { return downloadFile(url, TIMEOUT_MILLIS); } public static byte[] downloadFile(String url, long timeoutInMillis) throws IOException { OkHttpClient client = getOkHttpClient(timeoutInMillis); Request request = new Request.Builder().url(url).get().build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { return null; } return response.body().bytes(); } catch (IOException e) { throw e; } } private static OkHttpResp getResponse(OkHttpClient client, Request request) throws IOException { OkHttpResp resp = new OkHttpResp(); // 确保Response和ResponseBody关闭 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { resp.setSuccessful(false); } ResponseBody body = response.body(); resp.setSuccessful(true); resp.setRespStr(body.string()); resp.setRespHeaders(response.headers()); resp.setContentType(body.contentType()); resp.setContentLength(body.contentLength()); return resp; } catch (IOException e) { throw e; } } private static void addHeaders(Map<String, Object> reqHeaders, Request.Builder reqBuilder) { if (CollectionUtils.isEmpty(reqHeaders)) { return; } reqHeaders.forEach((headerName, headerValue) -> { reqBuilder.addHeader(headerName, String.valueOf(headerValue)); }); } public static class MultipartFile { /** * 文件域名,相当于表单中文件域名 */ private String fieldName; private String fileName; private byte[] content; public MultipartFile() { } public MultipartFile(String fieldName, String fileName, byte[] content) { 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; private MediaType contentType; private long contentLength; private boolean successful; public String getRespStr() { return respStr; } public Headers getRespHeaders() { return respHeaders; } public MediaType getContentType() { return contentType; } public long getContentLength() { return contentLength; } public boolean isSuccessful() { return successful; } public void setRespStr(String respStr) { this.respStr = respStr; } public void setRespHeaders(Headers respHeaders) { this.respHeaders = respHeaders; } public void setContentType(MediaType contentType) { this.contentType = contentType; } public void setContentLength(long contentLength) { this.contentLength = contentLength; } public void setSuccessful(boolean successful) { this.successful = successful; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } } }
对阿里FastJSONj进行JavaBean到json字符串映射的简单封装。
package com.universe.thirdparty.fastjson; import java.util.List; import java.util.Map; import java.util.Objects; import org.apache.commons.lang3.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.serializer.SerializeConfig; import com.alibaba.fastjson.serializer.SerializeFilter; import com.alibaba.fastjson.serializer.SerializerFeature; public class JsonUtils { public static String toJsonString(Object obj, SerializeFilter... filters) { return toJsonString(obj, null, false, false, filters); } public static String toJsonStringWithNullValue(Object obj, SerializeFilter... filters) { return toJsonString(obj, null, true, false, filters); } public static String toPrettyJsonString(Object obj, SerializeFilter... filters) { return toJsonString(obj, null, false, true, filters); } public static String toPrettyJsonStringWithNullValue(Object obj, SerializeFilter... filters) { return toJsonString(obj, null, true, true, filters); } public static String toJsonStringWithDateFormat(Object obj, String dateFormat, SerializeFilter... filters) { return toJsonString(obj, dateFormat, false, false, filters); } public static String toJsonStringWithDateFormatAndNullValue(Object obj, String dateFormat, SerializeFilter... filters) { return toJsonString(obj, dateFormat, true, false, filters); } public static String toPrettyJsonStringWithDateFormat(Object obj, String dateFormat, SerializeFilter... filters) { return toJsonString(obj, dateFormat, false, true, filters); } public static String toPrettyJsonStringWithDateFormatAndNullValue(Object obj, String dateFormat, SerializeFilter... filters) { return toJsonString(obj, dateFormat, true, true, filters); } public static String toJsonString(Object obj, String dateFormat, boolean writeNullValue, boolean prettyFormat, SerializeFilter... filters) { if (obj == null) { return null; } int defaultFeature = JSON.DEFAULT_GENERATE_FEATURE; if (writeNullValue) { return prettyFormat ? JSON.toJSONString(obj, SerializeConfig.globalInstance, filters, dateFormat, defaultFeature, SerializerFeature.WriteMapNullValue, SerializerFeature.PrettyFormat) : JSON.toJSONString(obj, SerializeConfig.globalInstance, filters, dateFormat, defaultFeature, SerializerFeature.WriteMapNullValue); } return prettyFormat ? JSON.toJSONString(obj, SerializeConfig.globalInstance, filters, dateFormat, defaultFeature, SerializerFeature.PrettyFormat) : JSON.toJSONString(obj, SerializeConfig.globalInstance, filters, dateFormat, defaultFeature); } public static <T> T toJavaBean(String jsonStr, Class<T> clazz) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseObject(jsonStr, clazz); } public static <T> List<T> toList(String jsonStr, Class<T> clazz) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseArray(jsonStr, clazz); } public static Map<String, Object> toMap(String jsonStr) { if (StringUtils.isBlank(jsonStr)) { return null; } return JSON.parseObject(jsonStr, new TypeReference<Map<String, Object>>() {}); } public static Map<String, Object> javaBeanToMap(Object obj) { if (Objects.isNull(obj)) { return null; } return toMap(toJsonString(obj)); } 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); } }