kotlin的HttpClient封裝http通信工具類

目的與初衷

最近在工作中需要在后臺調(diào)用第三方接口(微信肖粮,支付,華為點(diǎn)擊回?fù)芏啵ㄒ贿_(dá)物流快遞接口)涩馆,最近在學(xué)習(xí)Kotlin,嘗試使用Kotlin和HttpClient允坚,自己封裝了一個HttpClient工具類魂那,封裝常用實(shí)現(xiàn)get,post工具方法類

1 什么是HttpClient

HTTP 協(xié)議可能是現(xiàn)在 Internet 上使用得最多稠项、最重要的協(xié)議了涯雅,越來越多的 Java 應(yīng)用程序需要直接通過 HTTP 協(xié)議來訪問網(wǎng)絡(luò)資源。雖然在 JDK 的 java net包中已經(jīng)提供了訪問 HTTP 協(xié)議的基本功能展运,但是對于大部分應(yīng)用程序來說斩芭,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是Apache HttpComponents 下的子項(xiàng)目乐疆,用來提供高效的划乖、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包挤土,并且它支持 HTTP 協(xié)議最新的版本和建議琴庵。

2 功能介紹

  • 支持自動轉(zhuǎn)向
  • 支持 HTTPS 協(xié)議
  • 支持代理服務(wù)器等

3. 版本比較

注意本篇博客主要是基于 HttpClient4.5.5 版本的來講解的,也是現(xiàn)在最新的版本仰美,之所以要提供版本說明的是因?yàn)?HttpClient 3 版本和 HttpClient 4 版本差別還是很多大的迷殿,基本HttpClient里面的接口都變了,你把 HttpClient 3 版本的代碼拿到 HttpClient 4 上面都運(yùn)行不起來咖杂,會報錯的庆寺。所以一定要注意 HtppClient 的版本問題。

4. HttpClient不能做的事情

HttpClient 不是瀏覽器诉字,它是一個客戶端 HTTP 協(xié)議傳輸類庫懦尝。HttpClient 被用來發(fā)送和接受 HTTP 消息知纷。HttpClient 不會處理 HTTP 消息的內(nèi)容,不會進(jìn)行 javascript 解析陵霉,不會關(guān)心 content type琅轧,如果沒有明確設(shè)置,HttpClient 也不會對請求進(jìn)行格式化踊挠、重定向 url乍桂,或者其他任何和 HTTP 消息傳輸相關(guān)的功能。

5. HttpClient使用流程

使用HttpClient發(fā)送請求效床、接收響應(yīng)很簡單睹酌,一般需要如下幾步即可。

    1. 創(chuàng)建HttpClient對象剩檀。
    1. 創(chuàng)建請求方法的實(shí)例忍疾,并指定請求URL。如果需要發(fā)送GET請求谨朝,創(chuàng)建HttpGet對象卤妒;如果需要發(fā)送POST請求,創(chuàng)建HttpPost對象字币。
    1. 如果需要發(fā)送請求參數(shù)则披,可調(diào)用HttpGetsetParams方法來添加請求參數(shù);對于HttpPost對象而言洗出,可調(diào)用setEntity(HttpEntity entity)方法來設(shè)置請求參數(shù)士复。
    1. 調(diào)用HttpClient對象的execute(HttpUriRequest request)發(fā)送請求,該方法返回一個HttpResponse對象翩活。
    1. 調(diào)用HttpResponse的getAllHeaders()阱洪、getHeaders(String name)等方法可獲取服務(wù)器的響應(yīng)頭;調(diào)用HttpResponse的getEntity()方法可獲取HttpEntity對象菠镇,該對象包裝了服務(wù)器的響應(yīng)內(nèi)容冗荸。程序可通過該對象獲取服務(wù)器的響應(yīng)內(nèi)容。
    1. 釋放連接利耍。無論執(zhí)行方法是否成功蚌本,都必須釋放連接

6. HttpClient與Kotlin結(jié)合使用

package com.flong.kotlin.utils
import com.alibaba.fastjson.JSONObject
import com.flong.kotlin.utils.security.SSLContextSecurity
import org.apache.http.HttpStatus
import org.apache.http.NameValuePair
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.entity.UrlEncodedFormEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.conn.ssl.SSLContextBuilder
import org.apache.http.conn.ssl.TrustStrategy
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager
import org.apache.http.message.BasicNameValuePair
import org.apache.http.util.EntityUtils.consume
import org.apache.http.util.EntityUtils.toString
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.charset.Charset
import java.util.*
import java.util.stream.Collectors
import javax.net.ssl.HttpsURLConnection
/**
 * object表示這個類是單例模式
 * @Description HttpClientUtil幫助類
 * @Author      liangjilong
 * @Date        2018年12月17日 上午11:36:50
 */
object HttpClientUtil {
    private val log: Logger = LoggerFactory.getLogger(HttpClientUtil::class.java)

    private var JSON_APPLICATION        = "application/json; charset=utf-8"
    private var CONNECT_TIMEOUT         = 1000 * 20
    private var MAX_TIMEOUT             = 1000 * 20
    private var DEFAULT_ENCODING        = "UTF-8"
    private var LINE                    = System.getProperty("line.separator")//換行相當(dāng)于\n
    
    private val requestConfig : RequestConfig
    init {
        // 設(shè)置連接池  
        var connMgr = PoolingHttpClientConnectionManager()
        // 設(shè)置連接池大小  
        connMgr.maxTotal = 100
        connMgr.defaultMaxPerRoute = connMgr.maxTotal

        var configBuilder = RequestConfig.custom()
        // 設(shè)置連接超時  
        configBuilder.setConnectTimeout(MAX_TIMEOUT)
        // 設(shè)置讀取超時  
        configBuilder.setSocketTimeout(MAX_TIMEOUT)
        // 設(shè)置從連接池獲取連接實(shí)例的超時  
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT)
        // 在提交請求之前 測試連接是否可用  
        configBuilder.setStaleConnectionCheckEnabled(true)
        requestConfig = configBuilder.build()

    }


    /**
     * @Description 獲取參數(shù)內(nèi)容
     * @Author      liangjilong
     * @Date        2017年6月6日 上午11:36:50
     * @param bodyParameters
     * @throws UnsupportedEncodingException 參數(shù)
     * @return String 返回類型
     */
    fun getConcatParams(bodyParameters: Map<String, String>, encoding :String?): String? {
        
        var content   = ""
        //?: elvis操作符(貓王),encoding? 表示if(encoding != null) encoding else 表示為空的時候默認(rèn)就給 utf-8
        var charset   = encoding ?: "utf-8"
        
        var builder   = StringBuilder()
        for (i in bodyParameters.entries) {
            //將參數(shù)解析為"name=tom&age=21"的模式
            builder.append(i.key).append("=").append(URLEncoder.encode(i.value.toString(), charset)).append("&")
        }
        if (builder.length > 1) {
            content = builder.substring(0,builder.length -1)
        }
        return content
    }


    fun paramsToQueryString(bodyParameters: Map<String, String>) :String? {
        return bodyParameters.entries.stream().map({e -> e.key + "=" + e.value}).collect(Collectors.joining("&"))
    }


    //拼接參數(shù)同等getConcatParams方法,但是encode編碼
    fun paramsToQueryStringUrlencoded(bodyParameters: Map<String, String>,encoding :String?): String? {
        //?: elvis操作符(貓王),encoding? 表示if(encoding != null) encoding else 表示為空的時候默認(rèn)就給 utf-8
        var charset   = encoding ?: "utf-8"
        return bodyParameters.entries.stream().map({ e -> e.key + "=" + URLEncoder.encode(e.value, charset) }).collect(Collectors.joining("&"))
    }


    /**
     * @Description 請求鏈接返回InputStream
     * @Author        liangjl
     * @Date        2018年6月12日 下午8:37:42
     * @param reqUrl
     * @return 參數(shù)
     * @return InputStream 返回類型
     */
    fun createHttp(reqUrl: String): InputStream ? {
        try {
            var url = URL(reqUrl) // 創(chuàng)建URL
            var urlconn = url.openConnection() // 試圖連接并取得返回狀態(tài)碼
            urlconn.connect()
            var httpconn = urlconn as HttpURLConnection //把Connection轉(zhuǎn)換成HttpURLConnection
            if (httpconn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                log.error("createHttp方法出錯,無法連接到")
            } else {
                return urlconn.getInputStream()
            } 
        } catch (e: Exception) {
            log.error("createHttp方法出錯,出錯原因?yàn)?" + e.message)
        }
        return null
    }

    
    //創(chuàng)建http
    @JvmStatic
    private fun createHttp(reqUrl :String ,method: String,bodyParams:  String,
                   headers:Map<String,String>? ,charsetName :String?): String {

        val url  = URL(reqUrl)
        val conn = url.openConnection() as HttpURLConnection
        conn.requestMethod = method
        conn.doOutput   = true
        conn.doInput = true
        conn.useCaches = false
        conn.connectTimeout = CONNECT_TIMEOUT
        conn.readTimeout = CONNECT_TIMEOUT

        setRequestProperty(headers, conn)

        if (bodyParams.isNotEmpty()) {
            if (charsetName != null && "" != charsetName) {
                IoUtils.writerOutputStream(conn.outputStream, bodyParams, charsetName)
            } else {
                IoUtils.writerOutputStream(conn.outputStream, bodyParams)
            }
        }

        return IoUtils.getInputStream(conn.inputStream, charsetName)
    }
    
    
    /**
     * @Description 建立http請求鏈接支持SSL請求
     * @Author      liangjilong  
     * @Date        2017年6月6日 上午11:11:56  
     * @param reqUrl
     * @param requestMethod
     * @param outputStr
     * @param headerMap請求頭屬性,可以為空
     * @param sslVersion  支持https的版本參數(shù)(TLSv1, TLSv1.1  TLSv1.2)
     * @param bodyParameters  
     * @return String 返回類型   
     */
    @JvmStatic
    private fun createHttps(reqUrl: String, requestMethod: String, headerMap: Map<String, String>?,
                    sslVersion: String, bodyParameters: String?, encoding: String): String {
        
        var conn :HttpsURLConnection? = null
        try {
            //這行代碼必須要在創(chuàng)建URL對象之前隘梨,因?yàn)橄刃r?yàn)SSL的https請求通過才可以訪問http
            var ssf  = SSLContextSecurity.createIgnoreVerifySSL(sslVersion)
                
            var url  = URL(reqUrl)
         
            conn = url.openConnection() as HttpsURLConnection
            // 從上述SSLContext對象中得到SSLSocketFactory對象
            conn.sslSocketFactory   = ssf
            conn.doOutput           = true//輸出
            conn.doInput            = true//輸入
            conn.useCaches          = false//是否支持緩存
            conn.connectTimeout     = CONNECT_TIMEOUT
            conn.readTimeout        = CONNECT_TIMEOUT
            addRequestProperty(headerMap, conn)
            
            // 設(shè)置請求方式(GET/POST)
            conn.setRequestMethod(requestMethod)
            // 當(dāng)設(shè)置body請求參數(shù)
            if (bodyParameters != null && bodyParameters.isNotEmpty()) {  
                IoUtils.writerOutputStream(conn.getOutputStream(), bodyParameters)
            } 

            if(conn != null && conn.getResponseCode() == HttpStatus.SC_OK){
                // 從輸入流讀取返回內(nèi)容
                return IoUtils.getInputStream(conn.getInputStream(),encoding)
            }else{
                return IoUtils.getInputStream(conn.getInputStream(),encoding)
            }
        
        } catch (e :Exception)  {
            log.error("https請求異常:{}請求鏈接"+reqUrl,e)
            return ""http://請求系統(tǒng)頻繁
        }finally{
            // 釋放資源
            if(conn!=null){conn.disconnect()}
        }
    }
    
    
    /**
     * @Description 支持HttpClient的GET和POST請求,支持http和https協(xié)議
     * @Author  liangjl
     * @Date        2018年5月7日 下午10:05:28
     * @param reqUrl        請求鏈接
     * @param requestMethod 請求方法GET/POSt
     * @param bodyParameters 
     * @param encoding 編碼
     * @param headerMap 請求頭 
     * @return String 返回類型      
     */
   fun createHttp(reqUrl:String ,requestMethod :String, bodyParameters:Map<String,String>,
                     encoding :String?,headerMap:Map<String,String>?):String ?{  
        
        //這里是要轉(zhuǎn)成Java的String,因?yàn)閗otlin的String是沒有忽略大小寫這個方法
        //kotlin的==和equals是相同的都是比較字符串的值程癌,而且===三個等號比較的是地址的值.
        var method  = requestMethod as java.lang.String
        
        if((reqUrl.startsWith("https") || reqUrl.contains("https") )  && method.equalsIgnoreCase("POST")) {

            return commonHttpClientPost(reqUrl, bodyParameters, encoding, headerMap, createHttpClient())

        } else if((reqUrl.startsWith("http") || reqUrl.contains("http") )  && method.equalsIgnoreCase("POST")) {
            
            return commonHttpClientPost(reqUrl, bodyParameters, encoding, headerMap, HttpClients.createDefault())
            
        }else if((reqUrl.startsWith("https") || reqUrl.contains("https") )  && method.equalsIgnoreCase("GET")) {
            
            return commonHttpClientGet(reqUrl, bodyParameters, encoding, headerMap, createHttpClient())
            
        }else {
            return commonHttpClientGet(reqUrl, bodyParameters, encoding, headerMap, HttpClients.createDefault())
        }
   }

    /**
    * @Description 發(fā)送Post請求
    * @Author      liangjilong
    * @Email       jilongliang@sina.com
    * @Date        2017年10月31日 上午11:05:40
    * @param reqUrl 請求Url
    * @param bodyParameters
    * @return 參數(shù)
    * @return String 返回類型
     */
    fun createHttpPost(reqUrl:String, bodyParameters :List<BasicNameValuePair>):String  {
        var httpClient  = createHttpClient()
        var httpPost    = HttpPost(reqUrl)//創(chuàng)建HttpPost
        httpPost.config = requestConfig
        httpPost.entity = UrlEncodedFormEntity(bodyParameters, DEFAULT_ENCODING)//設(shè)置entity
        var httpResponse = httpClient.execute(httpPost)

        if (httpResponse.getStatusLine() != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            var retMsg = toString(httpResponse.getEntity(), DEFAULT_ENCODING)
            if (retMsg != null && retMsg.isNotEmpty()) {
                return retMsg
            }
        } else {
            return ""
        }
        return ""
    }

     /**
     * @Description commonHttpClientGet
     *  如:{'userName':'小梁','age':'100'}
     *  
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:35:09  
     * @param reqUrl 請求鏈接
     * @param bodyParameters 請求參數(shù)
     * @param encoding 編碼,不穿默認(rèn)UTF-8
     * @param headerMap 頭參數(shù):如 application/x-www-form-urlencoded charset=utf-8
     * @param httpClient
     * @return 參數(shù)  
     * @return String 返回類型
     */
     private fun commonHttpClientGet(reqUrl :String, bodyParameters:Map<String, String>?,encoding :String?,
                            headers: Map<String, String>?, httpClient:CloseableHttpClient):String? {
        var restMsg: String = ""
        var response: CloseableHttpResponse ?= null
        try {
            //把參數(shù)轉(zhuǎn)換成字符串
            var reqParamStr = toString(setUrlEncodedFormEntity(bodyParameters, encoding))
            var httpGet : HttpGet?
            if (reqParamStr != null && reqParamStr.isNotEmpty()) {
                
                httpGet = HttpGet(reqUrl + "?" + reqParamStr)
                log.info(".commonHttpClientGet,reqUrl:" + reqUrl + "?" + reqParamStr)
                
            } else {
                httpGet = HttpGet(reqUrl)
            }
            /*設(shè)置請求頭屬性和值 */
            if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                    var value = headers.get(key)
                    httpGet.addHeader(key, value)
                }
            }
            httpGet.setConfig(requestConfig)
            
            response = httpClient.execute(httpGet)
            var entity = response. getEntity()
            if (entity != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                restMsg = toString(entity, encoding)
                log.info(".commonHttpClientGet,請求鏈接為:" + reqUrl + ",Response Content: " + restMsg)
            } else {
                restMsg = ""
                log.error(".ommonHttpClientGet的entity對象為空" + reqUrl)
            }
        } catch (e: IOException) {
            log.error("commonHttpClientGet出現(xiàn)異常轴猎,異常信息為:" + e.message)
        } finally {
            if (response != null) {
                try {
                    consume(response.getEntity())
                } catch (e: IOException) {
                }
            }
        }
        return restMsg
    }
    
    
    /**
     * @Description commonHttpClientPost
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:34:43  
     * @param reqUrl
     * @param bodyParameters
     * @param contentType
     * @param encoding 編碼嵌莉,不傳默認(rèn)UTF-8
     * @param headerMap
     * @param httpClient
     * @return 參數(shù)  
     * @return String 返回類型
     */
    private fun commonHttpClientPost(reqUrl:String ,bodyParameters: Map<String, String> ?,
             encoding:String?,headerMap:Map<String, String>?,  httpClient:CloseableHttpClient):String {
        var restMsg:    String = ""
        var response:   CloseableHttpResponse? = null
        try {
            var httpPost    = setPostHeader(reqUrl, headerMap)/*設(shè)置請求頭屬性和值 */
            //把參數(shù)轉(zhuǎn)換成字符串
            var reqParamStr = toString(setUrlEncodedFormEntity(bodyParameters, encoding))
            httpPost.setConfig(requestConfig)
            setStringEntity(reqParamStr, encoding, httpPost)
            
            response = httpClient.execute(httpPost)
            
            var entity = response.getEntity()
            
            if (entity != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                var buffer = IoUtils.getInputStream(entity.getContent(), encoding)
                log.info(".commonHttpClientPost,reqUrl:" + reqUrl + ",Response content : " + buffer.toString())
                return buffer.toString()//返回  
            } else {
                var buffer = IoUtils.getInputStream(entity.getContent(), encoding)
                log.error(".commonHttpClientPost的entity對象為空,請求鏈接為:" + reqUrl)
                return buffer.toString()//返回  
            }
        } catch (e: IOException) {
            log.error("commonHttpClientPost出現(xiàn)異常,異常信息為:" + e.message)
        } finally {
            if (response != null) {
                response.close()
            }
            if (httpClient != null) {
                httpClient.close()
            }
        }
        return restMsg
    }  
   
    
     /**
     * @Description 創(chuàng)建UrlEncodedFormEntity參數(shù)對象實(shí)體 
     * 相當(dāng)于處理請求鏈接的參數(shù)如: -->http://www.yorisun.com/?username=yy&age=100
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:34:25  
     * @param bodyParameters
     * @param encoding
     * @param reqParamStr
     * @throws IOException
     * @throws UnsupportedEncodingException 參數(shù)  
     * @return String 返回類型
     */
     private fun setUrlEncodedFormEntity(bodyParameters :Map<String, String>?,  encoding:String?) :UrlEncodedFormEntity ? {
        
        if(bodyParameters != null && !bodyParameters.isEmpty()){
            //封裝請求參數(shù)  
            var params = ArrayList<NameValuePair>()
            for (entry in bodyParameters.entries) {  
                var key     = entry.key
                var `val`   = entry.value
                params.add(  BasicNameValuePair(key,  `val`))
            }
            var charset   = encoding ?: "utf-8"
            return  UrlEncodedFormEntity(params,Charset.forName(charset))
        }
        return null
    }  
    /**
     *設(shè)置頭屬性
     */
    private fun setRequestProperty(headers : Map<String, String>?, conn :HttpURLConnection) {
        
        if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                var value = headers.get(key)
                conn.setRequestProperty(key, value)
            }
        }
    }
    
     /**
     * @Description 添加請求屬性
     * @Author  liangjl
     * @Date        2018年5月7日 下午9:51:54
     * @param headerMap
     * @param conn 參數(shù)
     * @return void 返回類型 
     */
     @JvmStatic
     private fun addRequestProperty(headers :Map<String,String>?, conn :HttpsURLConnection) {
        /*設(shè)置請求頭屬性和值 */
        if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                 var value = headers.get(key)
                 //如:conn.addRequestProperty("Authorization","123456")
                 conn.addRequestProperty(key,value)
             }
        }
    }
    
    
    
     /**
     * @Description 創(chuàng)建Post的頭參數(shù)處理
     * @Author  liangjl
     * @Date        2018年4月25日 上午11:38:37
     * @param reqUrl
     * @param headerMap
     * @return 參數(shù)
     * @return HttpPost 返回類型 
     */
     @JvmStatic
     private  fun setPostHeader(reqUrl : String, headers :Map<String, String> ?) :HttpPost {
        var httpPost = HttpPost(reqUrl)  
        
        /*設(shè)置請求頭屬性和值 */
        if(headers != null &&headers.isNotEmpty()){
             for (key in  headers.keys) {
                 var value = headers.get(key)
                 //如: httpPost.addHeader("Content-Type", "application/json")  
                 httpPost.addHeader(key,value)
             }
        }
        return httpPost
    }  
    
     /**
     * @Description 設(shè)置setStringEntity參數(shù)
     * @Author  liangjl
     * @Date  2018年4月25日 下午12:23:57
     * @param bodyParameters
     * @param contentType 
     * @param encoding
     * @param httpPost 參數(shù)
     * @return void 返回類型 
     */
     @JvmStatic
     private  fun setStringEntity(bodyParameters : Any?,  encoding :String?,  httpPost :HttpPost) {
         if (bodyParameters  != null) {
             // 解決中文亂碼問題
             var charset      = encoding ?: "utf-8"
             var stringEntity = StringEntity(bodyParameters.toString(), charset)

             if (encoding != null && encoding.isNotEmpty()) {
                 stringEntity.setContentEncoding(encoding)
             }
             httpPost.setEntity(stringEntity)
         }
     }
    
    
    
    //創(chuàng)建httpClient
    @JvmStatic
    private  fun createHttpClient():CloseableHttpClient {
         val trustStrategy = object : TrustStrategy {
             override fun isTrusted(xcert509: Array<java.security.cert.X509Certificate>, arg1: String): Boolean {
                 return true
             }
         }
         var sslcontext = SSLContextBuilder().loadTrustMaterial(null,trustStrategy).build()

         var versions   = arrayOf( "TLSv1", "TLSv1.1", "TLSv1.2")
         var sslsf      = SSLConnectionSocketFactory(sslcontext,versions, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
         return HttpClients.custom().setSSLSocketFactory(sslsf).build()
     }
     
    
    @JvmStatic //main測試
    fun main(args: Array<String>) {
        //var b = mapOf("age" to 23, "userName" to "ljl")
        
        var map3 = HashMap<String,String>()
    
        map3.put("age","23")
        map3.put("userName","寅務(wù)")

        //var p = getConcatParams(map3,null)
        //var p = paramsToQueryString(map3)
        //println(p)
        var reqUrl = "http://localhost:8080/rest/getBody"
        var method = "POST"
        var json = JSONObject()
        json.put("passWord","123456")
        json.put("userName","寅務(wù)")
        
        var header =   HashMap<String, String>()
        header.put("Content-Type", JSON_APPLICATION)
        
        var retMsg = createHttp(reqUrl,method,json.toJSONString(),header,"utf-8")
        println("retMsg=" +retMsg)

    }

}

7捻脖、 ObjectUtil工具類

package com.flong.kotlin.utils

import org.apache.commons.lang3.StringUtils

import java.math.BigInteger

open class ObjectUtil {

    /**
     * @param object 關(guān)鍵字要用雙引號
     * @return
     */
    fun isNull(`object`: Any?): Boolean {
        return if (null == `object`) true else false
    }

    /**
     * @param object
     * *
     * @return
     */
    fun isNotNull(`object`: Any): Boolean {
        return !isNull(`object`)
    }

    /**
     * @param string
     * *
     * @return
     */
    fun isEmpty(string: String): Boolean {
        return StringUtils.isEmpty(string)
    }

    fun isNotEmpty(string: String?): Boolean {
        return StringUtils.isNotEmpty(string)
    }
    
    fun stringToBytes(hexString: String?): ByteArray? {
        var hexString = hexString
        if (hexString == null || hexString == "") {
            return null
        }
        hexString = hexString.toUpperCase()
        val length = hexString.length / 2
        val hexChars = hexString.toCharArray()
        val d = ByteArray(length)
        for (i in 0..length - 1) {
            val pos = i * 2
            d[i] = (charToByte(hexChars[pos]).toInt() shl 4 or charToByte(hexChars[pos + 1]).toInt()).toByte()
        }
        return d
    }

    /**
     * Convert char to byte
     * @param c char
     * *
     * @return byte
     */
    private fun charToByte(c: Char): Byte {
        return "0123456789ABCDEF".indexOf(c).toByte()
    }
    
    companion object{
        /**
         * 逗號
         */
        private const val COMMA_NAME: String = ","
    }


    /**
     * String 數(shù)組 轉(zhuǎn)換成 BigInteger 數(shù)組
     *
     * @param array String 數(shù)組
     * @return BigInteger 數(shù)組
     */
    fun string2BigInteger(array: Array<String>): ArrayList<BigInteger>? {
        val idArray: ArrayList<BigInteger> = arrayListOf()
        var id: BigInteger?
        for (i: Int in array.indices) {
            id = array[i].toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray.add(id)
            }
        }
        return idArray
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * String 數(shù)組 轉(zhuǎn)換成 BigInteger 數(shù)組
     *
     * @param array String 數(shù)組
     * @return BigInteger 數(shù)組
     */
    fun string2BigIntegerArray(array: Array<String>): Array<BigInteger>? {
        val idArray: Array<BigInteger> = Array(array.size, { BigInteger.ZERO })
        var id: BigInteger?
        for (i: Int in array.indices) {
            id = array[i].toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray[i] = id
            }
        }
        return idArray
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * String 轉(zhuǎn)換成 BigInteger 數(shù)組
     * @param str String
     * @return BigInteger 數(shù)組
     */
    fun string2BigInteger(str: String): Array<BigInteger>? {

        val strAry: List<String> = str.split(COMMA_NAME)
        val idArray: Array<BigInteger> = Array(strAry.size, { BigInteger.ZERO })
        var id: BigInteger?
        for ((i: Int, strValue: String) in strAry.withIndex()) {
            id = strValue.toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray[i] = id
            }
        }
        return idArray
    }
}

8锐峭、IoUtils工具類

package com.flong.kotlin.utils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.DataOutputStream
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.Arrays
import java.io.InputStreamReader
import java.io.BufferedReader
import java.lang.Byte
object IoUtils{
    private val log: Logger = LoggerFactory.getLogger(IoUtils::class.java) 
    /**
     * 點(diǎn)名稱
     */
    private const val DOT: String = "."

    /**
     * 點(diǎn)名稱
     */
    private const val SIZE_2MB: Long = 1024 * 1024 * 2
    
    /**
     * 獲取 classpath
     */
    val classpath: String?
        get() {
            var path: String? = Thread.currentThread().contextClassLoader.getResource("/").path
            if (null != path && 1 != path.indexOf(":")) {
                path = File.separator + path
            }
            return path
        }
    
    /**
     * 根據(jù)文件名 獲取其后綴信息
     *
     * @param fileSize 文件大小
     * @return String
     */
    @JvmStatic
    fun gt2Mb(fileSize: Long): Boolean {
        return fileSize > SIZE_2MB
    }
     /**
     * 根據(jù)文件名 獲取其后綴信息
     * @param filename 文件名
     * @return String
     */
    @JvmStatic
    fun getSuffixByFilename(filename: String): String {
        return filename.substring(filename.lastIndexOf(DOT) + 1).toLowerCase()
    }

    /**
     * 只刪除此路徑的最末路徑下所有文件和文件夾
     * @param folderPath 文件路徑
     */
    fun delFolder(folderPath: String) {
        try {
            // 刪除完里面所有內(nèi)容
            delAllFile(folderPath)
            val myFilePath = File(folderPath)
            // 刪除空文件夾
            myFilePath.delete()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 刪除指定文件夾下所有文件
     * @param path 文件夾完整絕對路徑
     * @return true/false
     */
    private fun delAllFile(path: String): Boolean {
        var flag = false
        val file = File(path)
        if (!file.exists()) {
            return false
        }
        if (!file.isDirectory) {
            return false
        }
        val tempList: Array<String>? = file.list()
        var temp: File
        if (null != tempList) {
            for (aTempList: String in tempList) {
                temp = if (path.endsWith(File.separator)) {
                    File(path + aTempList)
                } else {
                    File(path + File.separator + aTempList)
                }
                if (temp.isFile) {
                    temp.delete()
                }
                if (temp.isDirectory) {
                    // 先刪除文件夾里面的文件
                    delAllFile("$path/$aTempList")
                    // 再刪除空文件夾
                    delFolder("$path/$aTempList")
                    flag = true
                }
            }
        }
        return flag
    }

    // ------------------------------------------------

    /**
     * 創(chuàng)建文件夾
     * @param path 文件夾路徑
     * @return 文件夾路徑
     */
    @JvmStatic
    fun createPath(path: String): File {
        val file = File(path)
        try {
            if (!file.exists()) {
                file.mkdirs()
            }
        } catch (e: Exception) {
            //throw BaseException(">>創(chuàng)建[$path]文件夾失敗<<<<<")
            log.error(">>>創(chuàng)建[$path]文件夾失敗<<<<<<")
        }
        return file
    }
    
    
    //通過閉包返回來實(shí)現(xiàn)
    fun writeClo(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = -1
            `in`.use { input ->
                output.use {
                    while ({ read = input.read();read }() != -1) {
                        it.write(read)
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }

    //通過正常寫法來實(shí)現(xiàn)
    fun writeDef(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = `in`.read()
            `in`.use { input ->
                output.use {
                    while (read != -1) {
                        it.write(read)
                        read = input.read()
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }
    
    
    
    //通過使用also擴(kuò)展函數(shù)來實(shí)現(xiàn)
    fun writeAlso(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = -1
            `in`.use { input ->
                output.use {
                    while (input.read().also { read = it } != -1) {
                        it.write(read)
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }
    
    
    //拼接參數(shù)
    fun parameter(map: Map<String, Array<String>>): String {
         val stringBuilder = StringBuilder("")
         for ((key: String, value: Array<String>) in map) {
             stringBuilder.append("{")
             stringBuilder.append(key)
             stringBuilder.append("=")
             stringBuilder.append(Arrays.toString(value))
             stringBuilder.append("}")
             stringBuilder.append(",")
         }
         if (1 < stringBuilder.length) {
             stringBuilder.deleteCharAt(stringBuilder.toString().length - 1)
         }
         return stringBuilder.toString()
     }
    
    
    /*
     *讀取流的信息
     */
    fun getInputStream(`is` :InputStream, charsetName :String?):String {
        var charset = charsetName ?: "utf-8"
        val br = BufferedReader(InputStreamReader(`is`, charset))
        var line: String? = null
        val sb = StringBuilder()
        for (line in br.readLines()) {
            line?.let { sb.append(line) }
        }
        //關(guān)閉流
        if (br != null)   br.close();
        if (`is` != null) `is`.close();
        return sb.toString()
    }
    /**
     * @Description writerOutputStream
     * @Author  liangjl
     * @Date    2018年4月25日 下午12:05:16 參數(shù)
     * @return void 返回類型 
     */
    fun writerOutputStream(outputStream: OutputStream, bodyParameters: String) {
        var out = DataOutputStream(outputStream);
        out.writeBytes(bodyParameters);
        out.flush();
        out.close();
    }
    //寫入流處理
    fun writerOutputStream(outputStream: OutputStream, bodyParameters: String, encoding: String) {
        //強(qiáng)制轉(zhuǎn)換成Java的String對象
        var bodyParams = bodyParameters  as java.lang.String  
        var out = DataOutputStream(outputStream);
        out.write(bodyParams.getBytes(encoding))
        out.flush();
        out.close();
    }
} 

備注:此文章屬于本人原創(chuàng),歡迎轉(zhuǎn)載和收藏.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末中鼠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子只祠,更是在濱河造成了極大的恐慌,老刑警劉巖扰肌,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抛寝,死亡現(xiàn)場離奇詭異,居然都是意外死亡曙旭,警方通過查閱死者的電腦和手機(jī)盗舰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桂躏,“玉大人钻趋,你說我怎么就攤上這事〖料埃” “怎么了蛮位?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳞绕。 經(jīng)常有香客問我失仁,道長,這世上最難降的妖魔是什么们何? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任萄焦,我火速辦了婚禮,結(jié)果婚禮上冤竹,老公的妹妹穿的比我還像新娘拂封。我一直安慰自己,他們只是感情好鹦蠕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布冒签。 她就那樣靜靜地躺著,像睡著了一般钟病。 火紅的嫁衣襯著肌膚如雪镣衡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天档悠,我揣著相機(jī)與錄音廊鸥,去河邊找鬼。 笑死辖所,一個胖子當(dāng)著我的面吹牛惰说,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缘回,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼吆视,長吁一口氣:“原來是場噩夢啊……” “哼典挑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啦吧,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤您觉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后授滓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琳水,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年般堆,在試婚紗的時候發(fā)現(xiàn)自己被綠了在孝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡淮摔,死狀恐怖私沮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情和橙,我是刑警寧澤仔燕,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站魔招,受9級特大地震影響涨享,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仆百,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一厕隧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俄周,春花似錦吁讨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至波势,卻和暖如春翎朱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尺铣。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工拴曲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凛忿。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓澈灼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叁熔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • http-client-utli httpClient 工具類 github地址:https://github....
    楊文杰閱讀 5,108評論 0 5
  • 前言 前面一章中委乌,筆者向大家詳細(xì)講解了如何讓你的開發(fā)環(huán)境支持 Kotlin 以及如何在項(xiàng)目中配置使用 Kotlin...
    WangJie0822閱讀 4,305評論 0 4
  • 在一個春季的早晨醒來心软,我突然忘記了曾經(jīng)的故事是怎樣的一個開始壕吹,只有那些斷斷續(xù)續(xù)的記憶在慵懶的思緒里溫馨流淌。 一個...
    kaffu閱讀 376評論 0 0
  • 湯湯是我從小一起長大的閨蜜糯累。我們有時很久不聯(lián)系算利,然后忽然某一次定好時間地點(diǎn)直接約起册踩,廢話不多說泳姐,吃喝玩樂直奔主題。...
    八月牧歌閱讀 237評論 0 2
  • 因?yàn)橥碌慕ㄗh暂吉,參加了第三期的大頭早起成長營胖秒,也是因?yàn)樽x書組的這個作業(yè),讓我這很久沒寫過讀書筆記的人慕的,靜心心來想想...
    天天天藍(lán)201314閱讀 89評論 0 0