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 ...
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;
}
}