Java 呼叫http介面(基於OkHttp的Http工具類方法示例)
阿新 • • 發佈:2019-08-17
目錄
- Java 呼叫http介面(基於OkHttp的Http工具類方法示例)
- OkHttp3
- MAVEN依賴
- Http get操作示例
- Http Post操作示例
- Http 超時控制
- 工具類示例
Java 呼叫http介面(基於OkHttp的Http工具類方法示例)
現在的網際網路專案中,自己單擼所有功能的時代已經過去了,有些功能往往有第三方或者公司其他團隊提供服務,你要做得僅僅就是和它們進行對接。對接一些大公司提供的服務時,它們往往會提供對應語言的SDK和說明文件;而團隊與團隊之間的專案對接往往通過介面進行資料互動,往往都是HTTP JSON互動的形式。
本文介紹如何使用這些API,然後給出博主自己寫的一個工具列demo,需要的可以在此基礎上修改。
OkHttp3
一般來說,Java 直接呼叫HTTP介面常見的有三種方式,第一種是JDK原生的方式,第二種是apache 提供的HTTP工具,還有一種是本文著重介紹的OkHttp3工具
OkHttp3官方文件介紹了它的4點優勢:
- HTTP/2支援允許對同一主機的所有請求共享一個socket。
- 連線池減少了請求延遲(如果HTTP/2不可用)。
- 透明GZIP壓縮下載大小。
- 響應快取完全避免了網路重複請求。
使用OkHttp很容易。它的請求/響應API設計為流暢的構建器和不變性。它同時支援同步阻塞呼叫和帶回調的非同步呼叫。
下面介紹一下常見的GET方法和POST方法官方示例,首先新增依賴:
MAVEN依賴
<!--okhttp依賴-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.0.0</version>
</dependency>
Http get操作示例
OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } }
Http Post操作示例
public static final MediaType JSON
= MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
Http 超時控制
當呼叫的對等方不可用時,超時使呼叫失敗。網路可能是由於客戶機連線問題、伺服器可用性問題或兩者之間的任何問題造成的。OkHttp支援連線、讀取和寫入超時。
private final OkHttpClient client;
public ConfigureTimeouts() throws Exception {
client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response completed: " + response);
}
}
工具類示例
提供同步的GET和POST呼叫工具方法示例,提供了非同步呼叫HTTP介面的demo
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* @author axin
* @since 2019-08-14
*/
public class OkHttpUtils {
private static final Logger log = LoggerFactory.getLogger(OkHttpUtils.class);
private static final String HTTP_JSON = "application/json; charset=utf-8";
private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.build();
/**
* get請求
* 對於小文件,響應體上的string()方法非常方便和高效。
* 但是,如果響應主體很大(大於1 MB),則應避免string(),
* 因為它會將整個文件載入到記憶體中。在這種情況下,將主體處理為流。
*
* @param url
* @return
*/
public static String httpGet(String url) {
if (url == null || "".equals(url)) {
log.error("url為null!");
return "";
}
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
log.info("http GET 請求成功; [url={}]", url);
return response.body().string();
} else {
log.warn("Http GET 請求失敗; [errorCode = {} , url={}]", response.code(), url);
}
} catch (IOException e) {
throw new RuntimeException("同步http GET 請求失敗,url:" + url, e);
}
return null;
}
public static String httpGet(String url, Map<String, String> headers) {
if (CollectionUtils.isEmpty(headers)) {
return httpGet(url);
}
Request.Builder builder = new Request.Builder();
headers.forEach((String key, String value) -> builder.header(key, value));
Request request = builder.get().url(url).build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
log.info("http GET 請求成功; [url={}]", url);
return response.body().string();
} else {
log.warn("Http GET 請求失敗; [errorxxCode = {} , url={}]", response.code(), url);
}
} catch (IOException e) {
throw new RuntimeException("同步http GET 請求失敗,url:" + url, e);
}
return null;
}
/**
* 同步 POST呼叫 無Header
*
* @param url
* @param json
* @return
*/
public static String httpPostJson(String url, String json) {
if (url == null || "".equals(url)) {
log.error("url為null!");
return "";
}
MediaType JSON = MediaType.parse(HTTP_JSON);
RequestBody body = RequestBody.create(JSON, json);
Request.Builder requestBuilder = new Request.Builder().url(url);
Request request = requestBuilder.post(body).build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
log.info("http Post 請求成功; [url={}, requestContent={}]", url, json);
return response.body().string();
} else {
log.warn("Http POST 請求失敗; [ errorCode = {}, url={}, param={}]", response.code(), url, json);
}
} catch (IOException e) {
throw new RuntimeException("同步http請求失敗,url:" + url, e);
}
return null;
}
/**
* 同步 POST呼叫 有Header
*
* @param url
* @param headers
* @param json
* @return
*/
public static String httpPostJson(String url, Map<String, String> headers, String json) {
if (CollectionUtils.isEmpty(headers)) {
httpPostJson(url, json);
}
MediaType JSON = MediaType.parse(HTTP_JSON);
RequestBody body = RequestBody.create(JSON, json);
Request.Builder requestBuilder = new Request.Builder().url(url);
headers.forEach((k, v) -> requestBuilder.addHeader(k, v));
Request request = requestBuilder.post(body).build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
log.info("http Post 請求成功; [url={}, requestContent={}]", url, json);
return response.body().string();
} else {
log.warn("Http POST 請求失敗; [ errorCode = {}, url={}, param={}]", response.code(), url, json);
}
} catch (IOException e) {
throw new RuntimeException("同步http請求失敗,url:" + url, e);
}
return null;
}
/**
* 非同步Http呼叫參考模板:Get、Post、Put
* 需要非同步呼叫的介面一般情況下你需要定製一個專門的Http方法
*
* @param httpMethod
* @param url
* @param content
* @return
*/
@Deprecated
public static Future<Boolean> asyncHttpByJson(HttpMethod httpMethod, String url, Map<String, String> headers, String content) {
MediaType JSON = MediaType.parse(HTTP_JSON);
RequestBody body = RequestBody.create(JSON, content);
Request.Builder requestBuilder = new Request.Builder()
.url(url);
if (!CollectionUtils.isEmpty(headers)) {
headers.forEach((key, value) -> requestBuilder.header(key, value));
}
switch (httpMethod) {
case GET:
requestBuilder.get();
break;
case POST:
requestBuilder.post(body);
break;
default:
}
Request request = requestBuilder.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
log.error("非同步http {} 請求失敗,[url={}, param={}]", httpMethod.name(), url, content);
throw new RuntimeException("非同步http請求失敗,url:" + url);
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.code() == 200) {
System.out.println("需要加入非同步回撥操作");
} else {
log.error("非同步http {} 請求失敗,錯誤碼為{},請求引數為[url={}, param={}]", httpMethod.name(), response.code(), url, content);
}
}
});
return new AsyncResult(true);
}
/**
* lambda表示式非同步呼叫http模板,不建議使用
*
* @param request
* @param failure
* @param respConsumer
*/
public static void asyncCall(Request request, Consumer<Exception> failure, Consumer<Response> respConsumer) {
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failure.accept(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
respConsumer.accept(response);
}
});
}
//test
public static void main(String[] args) {
String url = "http://www.baidu.com";
System.out.println(httpGet(url));
}
}