白季飞龙的个人主页

OKHttp

OKHttp是一个Java的HTTP客户端,兼容性比Spring提供的RestTemplate要好(RestTemplate对于畸形HTTP头直接抛异常)

示例代码

package bj

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.Context
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import org.assertj.core.api.Assertions.assertThat
import org.glassfish.json.JsonUtil
import org.joda.time.DateTime
import org.joda.time.Duration
import org.slf4j.LoggerFactory
import tornadofx.*
import java.net.InetSocketAddress
import java.net.Proxy
import javax.json.JsonArray
import javax.json.JsonObject
import javax.json.JsonValue

/**
 * Created by BaiJiFeiLong@gmail.com at 18-9-28 下午2:13
 */

class MyHttpClient {
    private val okHttpClient = OkHttpClient.Builder().proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(1080))).build()
    private val logger = LoggerFactory.getLogger(this.javaClass)

    fun get(url: String, params: Map<String, String> = mapOf()): JsonValue {
        val httpUrl = HttpUrl.get(url).newBuilder().apply {
            params.forEach { t, u -> this.addQueryParameter(t, u) }
        }.build()
        val request = Request.Builder().url(httpUrl).build()
        logger.info(">>> GET $url")
        val response = okHttpClient.newCall(request).execute()
        assertThat(response.code()).isEqualTo(200)
        val text = response.body()!!.string()
        logger.info("<<< ${"%.100s${if (text.length > 100) " ..." else ""}".format(text)}")
        return JsonUtil.toJson(text)
    }
}

class BinanceApi {
    private val prefix = "https://api.binance.com/api"
    private val pingUrl = "$prefix/v1/ping"
    private val exchangeInfoUrl = "$prefix/v1/exchangeInfo"
    private val depthUrl = "$prefix/v1/depth"
    private val tradesUrl = "$prefix/v1/trades"
    private val historyUrl = "$prefix/v1/historicalTrades"
    private val klineUrl = "$prefix/v1/klines"

    private val myHttpClient = MyHttpClient()

    fun ping() {
        myHttpClient.get(pingUrl)
    }

    fun exchangeInfo(): JsonObject {
        return myHttpClient.get(exchangeInfoUrl).asJsonObject()
    }

    fun depth(): JsonObject {
        return myHttpClient.get(depthUrl, mapOf("symbol" to "BTCUSDT")).asJsonObject()
    }

    fun trades(): JsonArray {
        return myHttpClient.get(tradesUrl, mapOf("symbol" to "BTCUSDT")).asJsonArray()
    }

    fun history(): JsonArray {
        return myHttpClient.get(historyUrl, mapOf("symbol" to "BTCUSDT")).asJsonArray()
    }

    fun kline(): JsonArray {
        return myHttpClient.get(klineUrl, mapOf("symbol" to "BTCUSDT", "interval" to "1d")).asJsonArray()
    }
}


class TmpApp {
    private val binanceApi = BinanceApi()
    private val logger = LoggerFactory.getLogger(this.javaClass)

    private fun initLogging() {
        (LoggerFactory.getLogger("ROOT") as Logger).apply {
            level = Level.TRACE
            (getAppender("console") as ConsoleAppender).encoder = PatternLayoutEncoder().apply {
                context = LoggerFactory.getILoggerFactory() as Context
                pattern = "[%date] %highlight([%level]) [%logger{10} %file:%line] %msg%n"
                start()
            }
        }
    }

    private fun test() {
        binanceApi.ping()

        val exchangeInfo = binanceApi.exchangeInfo().asJsonObject()
        val timezone = exchangeInfo.getString("timezone")
        val timestamp = exchangeInfo.getLong("serverTime")
        val serverDateTime = DateTime(timestamp)
        val localDateTime = DateTime.now()
        logger.info("Server timezone: $timezone")
        logger.info("Server time: $serverDateTime")
        logger.info("Local  time: $localDateTime")
        logger.info("Server time behind of local ${Duration(serverDateTime, localDateTime).millis} milliseconds")

        binanceApi.depth()

        binanceApi.trades()

//        binanceApi.history()

        binanceApi.kline()
    }

    fun run() {
        initLogging()
        test()
    }
}

fun main(args: Array<String>) {
    TmpApp().run()
}

控制台输出

[2018-09-28 18:12:24,078] [INFO] [b.MyHttpClient TmpApp.kt:36] >>> GET https://api.binance.com/api/v1/ping
[2018-09-28 18:12:25,265] [INFO] [b.MyHttpClient TmpApp.kt:40] <<< {}
[2018-09-28 18:12:25,284] [INFO] [b.MyHttpClient TmpApp.kt:36] >>> GET https://api.binance.com/api/v1/exchangeInfo
[2018-09-28 18:12:25,582] [INFO] [b.MyHttpClient TmpApp.kt:40] <<< {"timezone":"UTC","serverTime":1538129545325,"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interv ...
[2018-09-28 18:12:25,650] [INFO] [bj.TmpApp TmpApp.kt:105] Server timezone: UTC
[2018-09-28 18:12:25,663] [INFO] [bj.TmpApp TmpApp.kt:106] Server time: 2018-09-28T18:12:25.325+08:00
[2018-09-28 18:12:25,663] [INFO] [bj.TmpApp TmpApp.kt:107] Local  time: 2018-09-28T18:12:25.650+08:00
[2018-09-28 18:12:25,664] [INFO] [bj.TmpApp TmpApp.kt:108] Server time behind of local 325 milliseconds
[2018-09-28 18:12:25,665] [INFO] [b.MyHttpClient TmpApp.kt:36] >>> GET https://api.binance.com/api/v1/depth
[2018-09-28 18:12:27,003] [INFO] [b.MyHttpClient TmpApp.kt:40] <<< {"lastUpdateId":255333286,"bids":[["6643.69000000","0.22870000",[]],["6643.66000000","2.00000000",[] ...
[2018-09-28 18:12:27,005] [INFO] [b.MyHttpClient TmpApp.kt:36] >>> GET https://api.binance.com/api/v1/trades
[2018-09-28 18:12:27,307] [INFO] [b.MyHttpClient TmpApp.kt:40] <<< [{"id":72581582,"price":"6646.65000000","qty":"0.12818900","time":1538129374380,"isBuyerMaker":false ...
[2018-09-28 18:12:27,314] [INFO] [b.MyHttpClient TmpApp.kt:36] >>> GET https://api.binance.com/api/v1/klines
[2018-09-28 18:12:27,792] [INFO] [b.MyHttpClient TmpApp.kt:40] <<< [[1502928000000,"4261.48000000","4485.39000000","4200.74000000","4285.08000000","795.15037700",15030 ...

POST示例

package com.ddweilai.microservice.kindergarten.system.provider.serviceimpl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vavr.control.Try;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.assertj.core.api.Assertions;

import java.util.Map;
import java.util.function.Function;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/12/20 下午4:16
 */
@Slf4j
class MyHttpClient {
    private OkHttpClient okHttpClient = new OkHttpClient();
    private ObjectMapper objectMapper = new ObjectMapper();

    @SuppressWarnings("ConstantConditions")
    JsonNode doGet(String url, Map<String, String> params) {
        HttpUrl.Builder httpUrlBuilder = HttpUrl.get(url).newBuilder();
        params.forEach(httpUrlBuilder::addQueryParameter);
        HttpUrl httpUrl = httpUrlBuilder.build();
        Request request = new Request.Builder().url(httpUrl).build();
        log.info(">>> [REQUEST] {}", request);
        Response response = Try.of(() -> okHttpClient.newCall(request).execute()).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        log.info(">>> [RESPONSE] {}", response);
        Assertions.assertThat(response.code()).isEqualTo(200);
        String text = Try.of(() -> response.body().string()).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        JsonNode node = Try.of(() -> objectMapper.readValue(text, JsonNode.class)).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        log.info("<<< [RESPONSE] [JSON] {}", node);
        return node;
    }

    @SuppressWarnings("ConstantConditions")
    JsonNode doPost(String url, Map<String, String> params) {
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        params.forEach(formBodyBuilder::add);
        FormBody formBody = formBodyBuilder.build();
        Request request = new Request.Builder().url(url).post(formBody).build();
        log.info(">>> [REQUEST] {}", request);
        Response response = Try.of(() -> okHttpClient.newCall(request).execute()).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        log.info(">>> [RESPONSE] {}", response);
        Assertions.assertThat(response.code()).isEqualTo(200);
        String text = Try.of(() -> response.body().string()).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        JsonNode node = Try.of(() -> objectMapper.readValue(text, JsonNode.class)).getOrElseThrow((Function<Throwable, RuntimeException>) RuntimeException::new);
        log.info("<<< [RESPONSE] [JSON] {}", node);
        return node;
    }
}

文章首发: https://baijifeilong.github.io


漫漫路,莫论逍遥;潜心修,只为悟道