1. 程式人生 > >OkHttp幫助類封裝

OkHttp幫助類封裝

package com.flong.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


/**
 * @Description 
 * ==========================================================================================
 * 參考部落格:http://www.cnblogs.com/whoislcj/p/5526431.html
 * 		  http://www.cnblogs.com/yinxiaoqiexuxing/p/5605338.html
 * ==========================================================================================
 * 秒的換算:ms(毫秒)millisecond ,μs(微秒)microsecond ,ns(納秒)nanosecond ,ps(皮秒)picosecond  
 * 秒的換算  http://blog.chinaunix.net/uid-28458801-id-4144886.html
 * Semaphored的使用: http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html 
 * ==========================================================================================
 * maven匯入okhttp與slf4j的jar 瀏覽器開啟maven倉庫輸入okhttp和slf4j即可,如下:
 * 倉庫官方網:---->>http://mvnrepository.com/
 * 
 * <dependency>
 *		    <groupId>com.squareup.okhttp3</groupId>
 *		    <artifactId>okhttp</artifactId>
 *		    <version>3.9.1</version>
 *	</dependency>
 * ==========================================================================================
 * @ClassName   OkHttpClientUtil  
 * @Date        2017年7月10日 下午5:39:49  
 * @Author      liangjilong  
 * @Copyright (c) All Rights Reserved, 2017.
 */
@SuppressWarnings("all")
public class OkHttpClientUtil {
	
	private static Logger logger = LoggerFactory.getLogger(OkHttpClientUtil.class);
	//private static String JSON = "application/json; charset=utf-8";
	private static String MEDIA_TYPE_JSON= "application/x-www-form-urlencoded; charset=utf-8";
	/**使用volatile雙重校驗鎖**/
	private static volatile Semaphore semaphore = null;
	private static volatile OkHttpClient okHttpClient = null; 
	
	/**建立單例模式*/
	public static  Semaphore getSemaphoreInstance(){
		//只能0個執行緒同時訪問
		synchronized (OkHttpClientUtil.class) {
			if (semaphore == null) {
				semaphore = new Semaphore(0);
			}
		}
		return semaphore;
	}
	
	
	/**建立單例模式*/
	public static  OkHttpClient getInstance(){
		synchronized (OkHttpClientUtil.class) {
			if (okHttpClient == null) {
				//這裡是以毫秒為單位,1000 毫秒 = 1秒
				okHttpClient = new OkHttpClient().newBuilder()
						.connectTimeout(5000, TimeUnit.SECONDS)// 設定超時時間
						.readTimeout(5000, TimeUnit.SECONDS)// 設定讀取超時時間
						.writeTimeout(5000, TimeUnit.SECONDS)// 設定寫入超時時間
						.build();
			}   
		}
		return okHttpClient;
	}
	
	
	public static void main(String[] args) throws Exception{
		/**組裝引數*/
		Map<String, Object> reqMap = new HashMap<String, Object>();
		reqMap.put("id", "1");
		
		//============================測試1==============================
		//String url = "http://localhost:8080/queryUserInfo?"+concatParams(reqMap).toString();
		//String retMsg = createAsycHttpPost(url,null,MEDIA_TYPE_JSON);
		
		
		//============================測試2==============================
		
		/*String url = "http://localhost:8080/queryUserInfo";
		createAsycHttpGet(url, reqMap, MEDIA_TYPE_JSON, new IOkHttpClientCallBack() {
			@Override
			public void onSuccessful(String retBody) {
				System.out.println(retBody);
			}
		});
		*/
		
		//============================測試3==============================
	 	/*String url = "http://localhost:8080/queryUserInfo";
	 	String retMsg = createHttpGet(url, reqMap, MEDIA_TYPE_JSON);
		
	 	System.out.println(retMsg);*/
		
		
		
		//============================測試4==============================
	 	/*String url = "http://localhost:8080/queryUserInfo";
	 	String retMsg = createAsycHttpPost(url, reqMap, MEDIA_TYPE_JSON);
		
	 	System.out.println(retMsg);*/
		
		//============================測試5==============================
		
		/*
		String url = "http://localhost:8080/queryUserInfo";
		String retMsg = createPostByAsynWithForm(url, reqMap);
		System.out.println(retMsg);*/
		
		
		//============================測試6==============================
		/*
		String url = "http://localhost:8080/queryUserInfo";
		String retMsg = createPostByAsynWithForm(url, reqMap);
		System.out.println(retMsg);*/
		
		
		//============================測試7==============================
		String url = "https://www.12306.cn/mormhweb/";
		String retMsg = createHttpsPost(url,null,MEDIA_TYPE_JSON);
	    System.out.println(retMsg);
		
	}
	
 
	/**
     * @Description 求在子執行緒發起網路請求
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午3:53:49  
     * @param url 請求url地址
     * @param params  請求body引數
     * @param okHttpClientCall 回撥介面
     * @throws IOException 引數  
     * @return void 返回型別
	 */
	public  static void createAsycHttpGet(String url,Map<String,Object> params,String contentType,final IOkHttpClientCallBack okHttpClientCall)  {
		// 建立請求物件
		Call call = createCall(url, params);
		
		//發起非同步的請求
 		call.enqueue(new Callback() {
			@Override
			public void onResponse(Call call, Response response) throws IOException {
				if (response!=null && response.isSuccessful()) {
					String string = response.body().string();
					okHttpClientCall.onSuccessful(string);
				}
			}
			@Override
			public void onFailure(Call call, IOException e) {
				String errorLog = getCurrentClassName()+"#createHttpGet,請求異常,異常資訊為:"+e.getMessage();
				logger.error("@see "+errorLog);
			}
		});
	}
	
	/**
     * @Description 求在子執行緒發起網路請求
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午3:53:49  
     * @param url 請求url地址
     * @param params  請求body引數
     * @param okHttpClientCall 回撥介面
     * @throws IOException 引數  
     * @return void 返回型別
	 */
	public static String createAsycHttpGet(String url,Map<String,Object> params,String contentType)  {
		final StringBuilder buffer = new StringBuilder("");
		try {
			// 建立請求物件
			Call call = createCall(url, params);
			
			//發起非同步的請求
			call.enqueue(new Callback() {
				@Override
				public void onResponse(Call call, Response response) throws IOException {

					if (response!=null && response.isSuccessful()) {
						String string = response.body().string();
						buffer.append(string);
						getSemaphoreInstance().release();
					}
				}
				@Override
				public void onFailure(Call call, IOException e) {
					String errorLog = getCurrentClassName()+"#createHttpGet,請求異常,異常資訊為:"+e.getMessage();
					logger.error("@see "+errorLog);
				}
			});
			getSemaphoreInstance().acquire();//獲取許可
			return buffer.toString();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return buffer.toString();
	}
	
	/**
     * @Description 求在子執行緒發起網路請求
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午3:53:49  
     * @param url 請求url地址
     * @param params  請求body引數
     * @param okHttpClientCall 回撥介面
     * @throws IOException 引數  
     * @return void 返回型別
	 */
	public static String createHttpGet(String url,Map<String,Object> params,String contentType)  {
		try {
			// 建立請求物件
			Call call = createCall(url, params);
			
			Response response = call.execute();
			if (response!=null && response.isSuccessful() && ObjectUtil.isNotEmpty(response.body())) {
				//Collection<String> readLines = IOUtil.readLines(byteStream);
				//System.out.println(readLines);
				return convertToString(response.body().byteStream());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	
	/**
	 * @Description convertStreamToString
	 * @Author		liangjl
	 * @Date		2018年2月9日 下午3:02:00
	 * @param is
	 * @return 引數
	 * @return String 返回型別 
	 * @throws
	 */
	public static String convertToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder buffer = new StringBuilder();
		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				buffer.append(line + "\r");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return buffer.toString();
	}
	
	/**
	 * @Description convertStr
	 * @Author		liangjl
	 * @Date		2018年2月9日 下午3:01:49
	 * @param is
	 * @return
	 * @throws IOException 引數
	 * @return String 返回型別 
	 * @throws
	 */
	public static String convertStr(InputStream is) throws IOException {
		OutputStream baos = new ByteArrayOutputStream();
		int i = -1;
		while ((i = is.read()) != -1) {
			baos.write(i);
		}
		return baos.toString();
	}
	/**
     * @Description 建立非同步表單Body引數的post請求處理  
     * @Author      liangjilong  
     * @Date        2017年7月11日 上午9:46:04  
     * @param url   請求連結
     * @param params 請求表單body引數
     * @param okHttpClientCall 引數  回撥介面
     * @return void 返回型別
	 */
	public static void createPostByAsynWithForm(String url,Map<String,Object> params,final IOkHttpClientCallBack okHttpClientCall)  {
		FormBody.Builder builder = new FormBody.Builder();
        for (String key : params.keySet()) {
            builder.add(key, params.get(key).toString());
        }
        RequestBody formBody = builder.build();
        logger.info("@see"+getCurrentClassName()+"請求url"+url+",請求引數:"+formBody);
        
        Request request = new Request.Builder().url(url).post(formBody).build();
        // 建立請求物件
 		Call call = getInstance().newCall(request);
 		//發起非同步的請求
 		call.enqueue(new Callback() {
			@Override
			public void onResponse(Call call, Response response) throws IOException {

				if (response!=null && response.isSuccessful()) {
					String string = response.body().string();
					okHttpClientCall.onSuccessful(string);
				}
			}
			
			@Override
			public void onFailure(Call call, IOException e) {
				String errorLog = getCurrentClassName()+"#createPostByAsynWithForm,請求異常,異常資訊為:"+e.getMessage();
				//okHttpClientCall.onFailure(errorLog);
				logger.error("@see "+errorLog);
			}
		});
	}
	
	
	/**
     * @Description 建立非同步表單Body引數的post請求處理  
     * @Author      liangjilong  
     * @Date        2017年7月11日 上午9:46:04  
     * @param url   請求連結
     * @param params 請求表單body引數
     * @param okHttpClientCall 引數  回撥介面
	 * @return 
     * @return void 返回型別
	 */
	public static String createPostByAsynWithForm(String url,Map<String,Object> params)  {
		final StringBuilder buffer = new StringBuilder("");
		try {
			FormBody.Builder builder = new FormBody.Builder();
			for (String key : params.keySet()) {
			    builder.add(key, params.get(key).toString());
			}
			RequestBody formBody = builder.build();
			logger.info("@see"+getCurrentClassName()+"請求url"+url+",請求引數:"+formBody);
			
			Request request = new Request.Builder().url(url).post(formBody).build();
			// 建立請求物件
			Call call = getInstance().newCall(request);
			//發起非同步的請求
			call.enqueue(new Callback() {
				@Override
				public void onResponse(Call call, Response response) throws IOException {

					if (response!=null && response.isSuccessful()) {
						String string = response.body().string();
						buffer.append(string);
						getSemaphoreInstance().release();
					}
				}
				
				@Override
				public void onFailure(Call call, IOException e) {
					String errorLog = getCurrentClassName()+"#createPostByAsynWithForm,請求異常,異常資訊為:"+e.getMessage();
					logger.error("@see "+errorLog);
				}
			});
			getSemaphoreInstance().acquire();
			return buffer.toString();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return buffer.toString();
	}
	
	 
	
	/**
     * okHttp createCall
     * @param url  介面地址
     * @param params   請求引數
     */
    private static Call createCall(String url, Map<String, Object> params) {
        //補全請求地址,【%s?%s或者%s/%s的使用】第一個%s代表第一個引數,第二個?代表是請求地址的?後面%s代表是組裝戳引數,如:
    	//http://localhost:8080/api/test.do?userId=1212&deviceInfo=PC
        String requestUrl = String.format("%s?%s", url, concatParams(params).toString());
        //建立一個請求
        Request request = new Request.Builder().url(requestUrl).build();
       return  getInstance().newCall(request);
    }
	
    
    /**
     * @Description createHttpPost  
     * @Author      liangjilong  
     * @Date        2017年7月11日 下午12:20:04  
     * @param url
     * @param reqMap
     * @param contentType
     * @return 引數  
     * @return String 返回型別
     */
    public static String createHttpPost(String url,Map<String,Object> reqMap,String contentType) {
    	try {
    		RequestBody body = createRequestBody(contentType, reqMap);
    		//logger.info("@see"+getCurrentClassName()+"#createHttpPost,請求url"+url+",請求引數:"+body.toString());
    		final Request request = new Request.Builder().url(url).post(body).build();
    		// 建立請求物件
    		final Call call = getInstance().newCall(request);
			Response response = call.execute();
			if (response!=null && response.isSuccessful()) {
				return convertStr(response.body().byteStream());
			} 
		} catch (IOException e) {
			e.printStackTrace();
		}
    	return "";
			
    }
		
	/**
     * @Description 在子執行緒發起 post 請求  
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午3:58:39  
     * @param url 引數  
     * @return void 返回型別
	 */
	public static String createAsycHttpPost(String url,Map<String,Object> reqMap,String contentType) {
		final StringBuilder buffer = new StringBuilder("");
		try {
			final RequestBody body = createRequestBody(contentType, reqMap);
			
			//logger.info("@see"+getCurrentClassName()+"#createHttpPost,請求url"+url+",請求引數:"+body.toString());
			final Request request = new Request.Builder().url(url).post(body).build();
			// 建立請求物件
			final Call call = getInstance().newCall(request);
			
			// 發起請求
			call.enqueue(new Callback() {
			    @Override
			    public void onFailure(Call call, IOException e) {
			    	String errorLog = getCurrentClassName()+"#createHttpPost,請求異常,異常資訊為:"+e.getMessage();
					logger.error("@see "+errorLog);
			    }
			    @Override
			    public void onResponse(Call call, Response response) throws IOException {
			         if (response!=null && response.isSuccessful()) {
			    	    if(ObjectUtil.isNotEmpty(response.body())){
			    	    	String string = response.body().string();
			    	    	buffer.append(string);
			    	    	getSemaphoreInstance().release();//釋放
			    	    }
					 }
			    }
			  });
			getSemaphoreInstance().acquire();//接受
			return  buffer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return buffer.toString();
	}
  
	/**
     * @Description 在子執行緒發起 post 請求  
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午3:58:39  
     * @param url 引數  
     * @return void 返回型別
	 */
	public static void createAsycHttpPost(String url,Map<String,Object> reqMap,String contentType,final IOkHttpClientCallBack okHttpClientCall) {
		final RequestBody body = createRequestBody(contentType, reqMap);
		
		//logger.info("@see"+getCurrentClassName()+"#createHttpPost,請求url"+url+",請求引數:"+body.toString());
		final Request request = new Request.Builder().url(url).post(body).build();
		// 建立請求物件
		final Call call = getInstance().newCall(request);
		
		// 發起請求
		call.enqueue(new Callback() {
		    @Override
		    public void onFailure(Call call, IOException e) {
		    	String errorLog = getCurrentClassName()+"#createHttpPost,請求異常,異常資訊為:"+e.getMessage();
				logger.error("@see "+errorLog);
		    }
		    @Override
		    public void onResponse(Call call, Response response) throws IOException {
		         if (response!=null && response.isSuccessful()) {
		    	    if(ObjectUtil.isNotEmpty(response.body())){
		    	    	String retBody = response.body().string();
		    	    	okHttpClientCall.onSuccessful(retBody);
		    	    }
				 }
		    }
		  });
	}
  
	/**
	 * 
     * @Description 組裝引數  
     * @Author      liangjilong  
     * @Date        2017年7月10日 下午5:48:13  
     * @param contentType  請求頭header屬性
     * @param params       請求引數
     * @return 引數  
     * @return RequestBody 返回型別
	 */
	private static RequestBody createRequestBody(String contentType,Map<String,Object> params){
		MediaType type = MediaType.parse(contentType);
        String paramStrs = concatParams(params).toString();
        return RequestBody.create(type, paramStrs);
	}



	/**
     * @Description 拼接引數  
     * @Author      liangjilong  
     * @Date        2017年7月11日 上午9:34:00  
     * @param params
     * @return 引數  
     * @return StringBuilder 返回型別
	 */
	private static StringBuilder concatParams(Map<String, Object> params) {
		StringBuilder builder = new StringBuilder("");//請求引數為空給一個預設值空字串
		//判斷是空
		if (ObjectUtil.isNotEmpty(params)) {
            int i = 0;
            for (String key : params.keySet()) {
                Object value = params.get(key);
                builder.append(i != 0 ? "&" : "");
                builder.append(key + "=" + value);
                i++;
            }
        }
		return builder;
	}
 
	
	/**
	 * @Description 建立支援https請求
	 * @Author		liangjl
	 * @Date		2018年2月9日 下午3:25:47
	 * @param url
	 * @param reqMap
	 * @param contentType 引數
	 * @return void 返回型別 
	 * @throws
	 */
	 public static String createHttpsPost(String url,Map<String,Object> reqMap,String contentType) {
		final StringBuilder buffer = new StringBuilder("");
		 /**忽略SSL協議證書*/
		
        OkHttpClient build = new OkHttpClient.Builder().sslSocketFactory(createSSLSocketFactory()).hostnameVerifier(new TrustAllHostnameVerifier()).build();
        
        final RequestBody body = createRequestBody(contentType, reqMap);
        
        final Request request  = new Request.Builder().url(url).post(body).build();
        final Call    call     = build.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                String res = response.body().string();
                buffer.append(res);
    	    	getSemaphoreInstance().release();//釋放
            }
        });
        
        try {
			getSemaphoreInstance().acquire();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		return  buffer.toString();
    }
	
	
	/**
	 * @Description	TrustAllCerts
	 * @ClassName	TrustAllCerts
	 * @Date		2018年2月9日 下午3:15:23
	 * @Author		liangjl
	 * @Copyright (c) All Rights Reserved, 2018.
	 */
	private static class TrustAllCerts implements X509TrustManager {
		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[0];
		}
	}

	/**
	 * @Description	驗證所有主機
	 * @ClassName	TrustAllHostnameVerifier
	 * @Date		2018年2月9日 下午3:15:34
	 * @Author		liangjl
	 * @Copyright (c) All Rights Reserved, 2018.
	 */
	private static class TrustAllHostnameVerifier implements HostnameVerifier {
		@Override
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}

	/**
	 * @Description createSSLSocketFactory
	 * @Author		liangjl
	 * @Date		2018年2月9日 下午3:15:47
	 * @return 引數
	 * @return SSLSocketFactory 返回型別 
	 * @throws
	 */
	private static SSLSocketFactory createSSLSocketFactory() {
		SSLSocketFactory ssfFactory = null;
		try {
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, new TrustManager[] { new TrustAllCerts() }, new SecureRandom());
			ssfFactory = sc.getSocketFactory();
		} catch (Exception e) {
		}
		return ssfFactory;
	}
	
	/**
	 * 
     * @Description 獲取當前類名包含有包名路徑  
     * @Author      liangjilong  
     * @Date        2017年5月24日 上午10:33:49  
     * @param @return 引數  
     * @return String 返回型別   
     * @throws
	 */
	public static String getCurrentClassName(){
		return OkHttpClientUtil.class.getName();
	}

	
	/**
	 * @Description	定義一個回撥成功的介面.
	 * @ClassName	IOkHttpClientCallBack
	 * @Date		2018年2月9日 下午3:34:18
	 * @Author		liangjl
	 * @Copyright (c) All Rights Reserved, 2018.
	 */
	public interface IOkHttpClientCallBack {

		void onSuccessful(String retBody);

	}
}

 

下載連結