Java 封装OkHttp3工具类,适用于Java后端开发者
说实在话,用过挺多网络请求工具,有过java原生的, HttpClient 3和4,但是个人感觉用了OkHttp3之后,之前的那些完全不想再用了。怎么说呢,代码轻便,使用起来很很很灵活,响应快,比起HttpClient好用许多。当然,这些是我个人观点,不喜勿喷。
准备工作
Maven 项目在pom文件中引入jar包
<dependency> | |
<groupId>com.squareup.okhttp</groupId> | |
<artifactId>okhttp</artifactId> | |
<version>.10.0</version> | |
</dependency> | |
<dependency> | |
<groupId>com.alibaba</groupId> | |
<artifactId> fastjson </artifactId> | |
<version>.2.60</version> | |
</dependency> |
引入 json 是因为工具类中有些地方用到了,现在通信都流行使用json传输,也少不了要这个jar包
工具类代码
import com.alibaba.fastjson.JSON; | |
import okhttp.*; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.SSLSocketFactory; | |
import javax.net. ssl .TrustManager; | |
import javax.net. SSL .X509TrustManager; | |
import java.io.IOException; | |
import java.net.URLEncoder; | |
import java.security.SecureRandom; | |
import java.security.cert.XCertificate; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
import java.util.concurrent.Semaphore; | |
import java.util.concurrent.TimeUnit; | |
public class OkHttpUtils { | |
private static volatile OkHttpClient okHttpClient = null; | |
private static volatile Semaphore semaphore = null; | |
private Map<String, String> headerMap; | |
private Map<String, String> paramMap; | |
private String url; | |
private Request.Builder request; | |
/** | |
* 初始化okHttpClient,并且允许https访问 | |
*/ private OkHttpUtils() { | |
if (okHttpClient == null) { | |
synchronized (OkHttpUtils.class) { | |
if (okHttpClient == null) { | |
TrustManager[] trustManagers = buildTrustManagers(); | |
okHttpClient = new OkHttpClient.Builder() | |
.connectTimeout(, TimeUnit.SECONDS) | |
.writeTimeout(, TimeUnit.SECONDS) | |
.readTimeout(, TimeUnit.SECONDS) | |
.sslSocketFactory(createSSLSocketFactory(trustManagers), (XTrustManager) trustManagers[0]) | |
.hostnameVerifier((hostName, session) -> true) | |
.retryOnConnectionFailure(true) | |
.build(); | |
addHeader("User-Agent", "Mozilla/.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"); | |
} | |
} | |
} | |
} | |
/** | |
* 用于异步请求时,控制访问线程数,返回结果 | |
* | |
* @return | |
*/ private static Semaphore getSemaphoreInstance() { | |
//只能个线程同时访问 | |
synchronized (OkHttpUtils.class) { | |
if (semaphore == null) { | |
semaphore = new Semaphore(); | |
} | |
} | |
return semaphore; | |
} | |
/** | |
* 创建OkHttpUtils | |
* | |
* @return | |
*/ public static OkHttpUtils builder() { | |
return new OkHttpUtils(); | |
} | |
/** | |
* 添加url | |
* | |
* @param url | |
* @return | |
*/ public OkHttpUtils url(String url) { | |
this.url = url; | |
return this; | |
} | |
/** | |
* 添加参数 | |
* | |
* @param key 参数名 | |
* @param value 参数值 | |
* @return | |
*/ public OkHttpUtils addParam(String key, String value) { | |
if (paramMap == null) { | |
paramMap = new LinkedHashMap<>(); | |
} | |
paramMap.put(key, value); | |
return this; | |
} | |
/** | |
* 添加请求头 | |
* | |
* @param key 参数名 | |
* @param value 参数值 | |
* @return | |
*/ public OkHttpUtils addHeader(String key, String value) { | |
if (headerMap == null) { | |
headerMap = new LinkedHashMap<>(); | |
} | |
headerMap.put(key, value); | |
return this; | |
} | |
/** | |
* 初始化get方法 | |
* | |
* @return | |
*/ public OkHttpUtils get() { | |
Request = new Request.Builder().get(); | |
StringBuilder urlBuilder = new StringBuilder (url); | |
if (paramMap != null) { | |
urlBuilder.append("?"); | |
try { | |
for (Map.Entry<String, String> entry : paramMap.entrySet()) { | |
urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-")). | |
append("="). | |
append(URLEncoder.encode(entry.getValue(), "utf-")). | |
append("&"); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
urlBuilder.deleteCharAt(urlBuilder.length() - ); | |
} | |
request.url(urlBuilder.toString()); | |
return this; | |
} | |
/** | |
* 初始化post方法 | |
* | |
* @param isJsonPost true等于json的方式提交数据,类似postman里post方法的raw | |
* false等于普通的表单提交 | |
* @return | |
*/ public OkHttpUtils post(boolean isJsonPost) { | |
RequestBody requestBody; | |
if (isJsonPost) { | |
String json = ""; | |
if (paramMap != null) { | |
json = JSON.toJSONString(paramMap); | |
} | |
request Body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json); | |
} else { | |
FormBody.Builder formBody = new FormBody.Builder(); | |
if (paramMap != null) { | |
paramMap.forEach(formBody::add); | |
} | |
requestBody = formBody.build(); | |
} | |
request = new Request.Builder().post(requestBody).url(url); | |
return this; | |
} | |
/** | |
* 同步请求 | |
* | |
* @return | |
*/ public String sync() { | |
setHeader(request); | |
try { | |
Response response = okHttpClient.newCall(request.build()).execute(); | |
assert response.body() != null; | |
return response.body().string(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return "请求失败:" + e.getMessage(); | |
} | |
} | |
/** | |
* 异步请求,有返回值 | |
*/ public String async() { | |
StringBuilder buffer = new StringBuilder(""); | |
setHeader(request); | |
okHttpClient.newCall(request.build()).enqueue(new Callback() { | |
@ Override | |
public void onFailure(Call call, IOException e) { | |
buffer.append("请求出错:").append(e.getMessage()); | |
} | |
public void onResponse(Call call, Response response) throws IOException { | |
assert response.body() != null; | |
buffer.append(response.body().string()); | |
getSemaphoreInstance().release(); | |
} | |
}); | |
try { | |
getSemaphoreInstance().acquire(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
return buffer.toString(); | |
} | |
/** | |
* 异步请求,带有接口回调 | |
* | |
* @param callBack | |
*/ public void async(ICallBack callBack) { | |
setHeader(request); | |
okHttpClient.newCall(request.build()).enqueue(new Callback() { | |
public void onFailure(Call call, IOException e) { | |
callBack.onFailure(call, e.getMessage()); | |
} | |
public void onResponse(Call call, Response response) throws IOException { | |
assert response.body() != null; | |
callBack.onSuccessful(call, response.body().string()); | |
} | |
}); | |
} | |
/** | |
* 为request添加请求头 | |
* | |
* @param request | |
*/ private void setHeader(Request.Builder request) { | |
if (headerMap != null) { | |
try { | |
for (Map.Entry<String, String> entry : headerMap.entrySet()) { | |
request.addHeader(entry.getKey(), entry.getValue()); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
/** | |
* 生成安全套接字工厂,用于https请求的证书跳过 | |
* | |
* @return | |
*/ private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) { | |
SSLSocketFactory ssfFactory = null; | |
try { | |
SSLContext sc = SSLContext.getInstance("SSL"); | |
sc.init(null, trustAllCerts, new SecureRandom()); | |
ssfFactory = sc.getSocketFactory(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return ssfFactory; | |
} | |
private static TrustManager[] buildTrustManagers() { | |
return new TrustManager[]{ | |
new XTrustManager() { | |
public void checkClientTrusted(XCertificate[] chain, String authType) { | |
} | |
public void checkServerTrusted(XCertificate[] chain, String authType) { | |
} | |
public XCertificate[] getAcceptedIssuers() { | |
return new XCertificate[]{}; | |
} | |
} | |
}; | |
} | |
/** | |
* 自定义一个接口回调 | |
*/ public interface ICallBack { | |
void onSuccessful(Call call, String data); | |
void onFailure(Call call, String errorMsg); | |
} | |
} |
使用教程
public static void main(String[] args) { | |
// get请求,方法顺序按照这种方式,切记选择post/get一定要放在倒数第二,同步或者异步倒数第一,才会正确执行 | |
OkHttpUtils.builder().url("请求地址,http/https都可以") | |
// 有参数的话添加参数,可多个 | |
.addParam("参数名", "参数值") | |
.addParam("参数名", "参数值") | |
// 也可以添加多个 | |
.addHeader("Content-Type", "application/json; charset=utf-") | |
.get() | |
// 可选择是同步请求还是异步请求 | |
//.async(); | |
.sync(); | |
// post请求,分为两种,一种是普通表单提交,一种是json提交 | |
OkHttpUtils.builder().url("请求地址,http/https都可以") | |
// 有参数的话添加参数,可多个 | |
.addParam("参数名", "参数值") | |
.addParam("参数名", "参数值") | |
// 也可以添加多个 | |
.addHeader("Content-Type", "application/json; charset=utf-") | |
// 如果是true的话,会类似于postman中post提交方式的raw,用json的方式提交,不是表单 | |
// 如果是 false 的话传统的表单提交 | |
.post(true) | |
.sync(); | |
// 选择异步有两个方法,一个是带回调接口,一个是直接返回结果 | |
OkHttpUtils.builder().url("") | |
.post(false) | |
.async(); | |
OkHttpUtils.builder().url("").post(false).async(new OkHttpUtils.ICallBack() { | |
public void onSuccessful(Call call, String data) { | |
// 请求成功后的处理 | |
} | |
public void onFailure(Call call, String errorMsg) { | |
// 请求失败后的处理 | |
} | |
}); | |
} |
结语
封装的明明白白,使用的简简单单,简单的几下就能做请求,用建造者模式是真的舒服