HttpClient.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. package com.guiying.common.http;
  2. import android.support.annotation.NonNull;
  3. import android.text.TextUtils;
  4. import com.franmontiel.persistentcookiejar.ClearableCookieJar;
  5. import com.franmontiel.persistentcookiejar.PersistentCookieJar;
  6. import com.franmontiel.persistentcookiejar.cache.SetCookieCache;
  7. import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;
  8. import com.guiying.common.R;
  9. import com.guiying.common.utils.NetworkUtils;
  10. import com.guiying.common.utils.StringUtils;
  11. import com.guiying.common.utils.ToastUtils;
  12. import com.guiying.common.utils.Utils;
  13. import com.orhanobut.logger.Logger;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.HashMap;
  17. import java.util.List;
  18. import java.util.Map;
  19. import java.util.concurrent.TimeUnit;
  20. import okhttp3.OkHttpClient;
  21. import okhttp3.ResponseBody;
  22. import retrofit2.Call;
  23. import retrofit2.Callback;
  24. import retrofit2.Response;
  25. import retrofit2.Retrofit;
  26. /**
  27. * <p>类说明</p>
  28. *
  29. * @author 张华洋 2016/12/5 14:09
  30. * @version V1.0.0
  31. * @name HttpClient
  32. */
  33. public class HttpClient {
  34. /*The certificate's password*/
  35. private static final String STORE_PASS = "6666666";
  36. private static final String STORE_ALIAS = "666666";
  37. /*用户设置的BASE_URL*/
  38. private static String BASE_URL = "";
  39. /*本地使用的baseUrl*/
  40. private String baseUrl = "";
  41. private static OkHttpClient okHttpClient;
  42. private Builder mBuilder;
  43. private Retrofit retrofit;
  44. private Call<ResponseBody> mCall;
  45. private static final Map<String, Call> CALL_MAP = new HashMap<>();
  46. /**
  47. * 获取HttpClient的单例
  48. *
  49. * @return HttpClient的唯一对象
  50. */
  51. private static HttpClient getIns() {
  52. return HttpClientHolder.sInstance;
  53. }
  54. /**
  55. * 单例模式中的静态内部类写法
  56. */
  57. private static class HttpClientHolder {
  58. private static final HttpClient sInstance = new HttpClient();
  59. }
  60. private HttpClient() {
  61. ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(Utils.getContext()));
  62. //HttpsUtil.SSLParams sslParams = HttpsUtil.getSslSocketFactory(Utils.getContext(), R.raw.cer,STORE_PASS , STORE_ALIAS);
  63. okHttpClient = new OkHttpClient.Builder()
  64. .connectTimeout(10000L, TimeUnit.MILLISECONDS)
  65. //.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
  66. // .hostnameVerifier(HttpsUtil.getHostnameVerifier())
  67. .addInterceptor(new LoggerInterceptor(null, true))
  68. .cookieJar(cookieJar)
  69. .build();
  70. }
  71. public Builder getBuilder() {
  72. return mBuilder;
  73. }
  74. private void setBuilder(Builder builder) {
  75. this.mBuilder = builder;
  76. }
  77. /**
  78. * 获取的Retrofit的实例,
  79. * 引起Retrofit变化的因素只有静态变量BASE_URL的改变。
  80. */
  81. private void getRetrofit() {
  82. if (!BASE_URL.equals(baseUrl) || retrofit == null) {
  83. baseUrl = BASE_URL;
  84. retrofit = new Retrofit.Builder()
  85. .baseUrl(baseUrl)
  86. .client(okHttpClient)
  87. .build();
  88. }
  89. }
  90. public void post(final OnResultListener onResultListener) {
  91. Builder builder = mBuilder;
  92. mCall = retrofit.create(ApiService.class)
  93. .executePost(builder.url, builder.params);
  94. putCall(builder, mCall);
  95. request(builder, onResultListener);
  96. }
  97. public void get(final OnResultListener onResultListener) {
  98. Builder builder = mBuilder;
  99. if (!builder.params.isEmpty()) {
  100. String value = "";
  101. for (Map.Entry<String, String> entry : builder.params.entrySet()) {
  102. String mapKey = entry.getKey();
  103. String mapValue = entry.getValue();
  104. String span = value.equals("") ? "" : "&";
  105. String part = StringUtils.buffer(span, mapKey, "=", mapValue);
  106. value = StringUtils.buffer(value, part);
  107. }
  108. builder.url(StringUtils.buffer(builder.url, "?", value));
  109. }
  110. mCall = retrofit.create(ApiService.class).executeGet(builder.url);
  111. putCall(builder, mCall);
  112. request(builder, onResultListener);
  113. }
  114. private void request(final Builder builder, final OnResultListener onResultListener) {
  115. if (!NetworkUtils.isConnected()) {
  116. ToastUtils.showLongToastSafe(R.string.current_internet_invalid);
  117. onResultListener.onFailure(Utils.getString(R.string.current_internet_invalid));
  118. return;
  119. }
  120. mCall.enqueue(new Callback<ResponseBody>() {
  121. @Override
  122. public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
  123. if (200 == response.code()) {
  124. try {
  125. String result = response.body().string();
  126. parseData(result, builder.clazz, builder.bodyType, onResultListener);
  127. } catch (IOException e) {
  128. e.printStackTrace();
  129. }
  130. }
  131. if (!response.isSuccessful() || 200 != response.code()) {
  132. onResultListener.onError(response.code(), response.message());
  133. }
  134. if (null != builder.tag) {
  135. removeCall(builder.url);
  136. }
  137. }
  138. @Override
  139. public void onFailure(Call<ResponseBody> call, Throwable t) {
  140. t.printStackTrace();
  141. onResultListener.onFailure(t.getMessage());
  142. if (null != builder.tag) {
  143. removeCall(builder.url);
  144. }
  145. }
  146. });
  147. }
  148. /**
  149. * 添加某个请求
  150. */
  151. private synchronized void putCall(Builder builder, Call call) {
  152. if (builder.tag == null)
  153. return;
  154. synchronized (CALL_MAP) {
  155. CALL_MAP.put(builder.tag.toString() + builder.url, call);
  156. }
  157. }
  158. /**
  159. * 取消某个界面都所有请求,或者是取消某个tag的所有请求;
  160. * 如果要取消某个tag单独请求,tag需要传入tag+url
  161. *
  162. * @param tag 请求标签
  163. */
  164. public synchronized void cancel(Object tag) {
  165. if (tag == null)
  166. return;
  167. List<String> list = new ArrayList<>();
  168. synchronized (CALL_MAP) {
  169. for (String key : CALL_MAP.keySet()) {
  170. if (key.startsWith(tag.toString())) {
  171. CALL_MAP.get(key).cancel();
  172. list.add(key);
  173. }
  174. }
  175. }
  176. for (String s : list) {
  177. removeCall(s);
  178. }
  179. }
  180. /**
  181. * 移除某个请求
  182. *
  183. * @param url 添加的url
  184. */
  185. private synchronized void removeCall(String url) {
  186. synchronized (CALL_MAP) {
  187. for (String key : CALL_MAP.keySet()) {
  188. if (key.contains(url)) {
  189. url = key;
  190. break;
  191. }
  192. }
  193. CALL_MAP.remove(url);
  194. }
  195. }
  196. /**
  197. * Build a new HttpClient.
  198. * url is required before calling. All other methods are optional.
  199. */
  200. public static final class Builder {
  201. private String builderBaseUrl = "";
  202. private String url;
  203. private Object tag;
  204. private Map<String, String> params = new HashMap<>();
  205. /*返回数据的类型,默认是string类型*/
  206. @DataType.Type
  207. private int bodyType = DataType.STRING;
  208. /*解析类*/
  209. private Class clazz;
  210. public Builder() {
  211. }
  212. /**
  213. * 请求地址的baseUrl,最后会被赋值给HttpClient的静态变量BASE_URL;
  214. *
  215. * @param baseUrl 请求地址的baseUrl
  216. */
  217. public Builder baseUrl(String baseUrl) {
  218. this.builderBaseUrl = baseUrl;
  219. return this;
  220. }
  221. /**
  222. * 除baseUrl以外的部分,
  223. * 例如:"mobile/login"
  224. *
  225. * @param url path路径
  226. */
  227. public Builder url(String url) {
  228. this.url = url;
  229. return this;
  230. }
  231. /**
  232. * 给当前网络请求添加标签,用于取消这个网络请求
  233. *
  234. * @param tag 标签
  235. */
  236. public Builder tag(Object tag) {
  237. this.tag = tag;
  238. return this;
  239. }
  240. /**
  241. * 添加请求参数
  242. *
  243. * @param key 键
  244. * @param value 值
  245. */
  246. public Builder params(String key, String value) {
  247. this.params.put(key, value);
  248. return this;
  249. }
  250. /**
  251. * 响应体类型设置,如果要响应体类型为STRING,请不要使用这个方法
  252. *
  253. * @param bodyType 响应体类型,分别:STRING,JSON_OBJECT,JSON_ARRAY,XML
  254. * @param clazz 指定的解析类
  255. * @param <T> 解析类
  256. */
  257. public <T> Builder bodyType(@DataType.Type int bodyType, @NonNull Class<T> clazz) {
  258. this.bodyType = bodyType;
  259. this.clazz = clazz;
  260. return this;
  261. }
  262. public HttpClient build() {
  263. if (!TextUtils.isEmpty(builderBaseUrl)) {
  264. BASE_URL = builderBaseUrl;
  265. }
  266. HttpClient client = HttpClient.getIns();
  267. client.getRetrofit();
  268. client.setBuilder(this);
  269. return client;
  270. }
  271. }
  272. /**
  273. * 数据解析方法
  274. *
  275. * @param data 要解析的数据
  276. * @param clazz 解析类
  277. * @param bodyType 解析数据类型
  278. * @param onResultListener 回调方数据接口
  279. */
  280. @SuppressWarnings("unchecked")
  281. private void parseData(String data, Class clazz, @DataType.Type int bodyType, OnResultListener onResultListener) {
  282. switch (bodyType) {
  283. case DataType.STRING:
  284. onResultListener.onSuccess(data);
  285. break;
  286. case DataType.JSON_OBJECT:
  287. onResultListener.onSuccess(DataParseUtil.parseObject(data, clazz));
  288. break;
  289. case DataType.JSON_ARRAY:
  290. onResultListener.onSuccess(DataParseUtil.parseToArrayList(data, clazz));
  291. break;
  292. case DataType.XML:
  293. onResultListener.onSuccess(DataParseUtil.parseXml(data, clazz));
  294. break;
  295. default:
  296. Logger.e("http parse tip:", "if you want return object, please use bodyType() set data type");
  297. break;
  298. }
  299. }
  300. }