A simple http client framework based on HttpURLConnection wrapper
MiniHttpClient
一:開發(fā)環(huán)境
Mac OS 10、Java 1.8、IDEA(Gradle工程)
二:介紹
基于Java HttpURLConnection實(shí)現(xiàn)Http客戶端,支持普通接口請(qǐng)求和表單上傳文件及文件下載等。使用線程池實(shí)現(xiàn)同步Future和異步請(qǐng)求。
目前判斷以下ContentType為文本接收,其余認(rèn)為文件下載:
ContentType |
類型 |
說明 |
空 |
空 |
沒有指明數(shù)據(jù)類型,默認(rèn)按文本處理 |
application/json |
Json文本 |
常見接口請(qǐng)求 |
text/html |
htm或者h(yuǎn)tml等 |
網(wǎng)頁(yè)文件 |
text/plain |
純文本 |
txt等文件,以文本返回,不按文件下載 |
text/xml |
xml類文件 |
xml及其衍生文件格式大多數(shù)用這種類型 |
三:特點(diǎn)
- 純Java API實(shí)現(xiàn),輕巧。
- 支持同步和異步兩種方式。
- 獨(dú)立線程發(fā)起請(qǐng)求,支持線程池管理。
- 支持POST表單數(shù)據(jù)和文件上傳。
- 方便擴(kuò)展,自定義功能。
- Maven
<dependency>
<groupId>com.itgowo</groupId>
<artifactId>MiniHttpClient</artifactId>
<version>0.0.43</version>
<type>pom</type>
</dependency>
- Gradle
implementation 'com.itgowo:MiniHttpClient:0.0.43'
五:簡(jiǎn)單使用(庫(kù)Jar中有Demo類,可以參考)
Demo.java
1.模擬表單上傳,POST方式
public static void testUploadFile() {
String url = "http://127.0.0.1:12111";
List<File> files = new ArrayList<>();
File file = new File("/Users/lujianchao/Desktop/RDC1.png");
files.add(file);
HttpClient.RequestUploadFiles(url, null, files, new onSimpleCallbackListener() {
@Override
public void onError(HttpResponse httpResponse, Exception e) {
System.out.println("httpResponse = [" + httpResponse + "], e = [" + e + "]");
}
@Override
public void onProcess(File file, int countBytes, int processBytes) throws Exception {
System.out.println("file = [" + file + "], countBytes = [" + countBytes + "], processBytes = [" + processBytes + "]");
}
@Override
public void onSuccess(HttpResponse httpResponse) throws Exception {
System.out.println("httpResponse = [" + httpResponse + "]");
}
});
}
2.同步上傳文件
public static void testSyncUploadFile() throws Exception {
String url = "http://127.0.0.1:12111/app.js";
List<File> files = new ArrayList<>();
File file = new File("/Users/lujianchao/Desktop/RDC1.png");
files.add(file);
HttpResponse httpResponse = HttpClient.RequestSync(url, HttpMethod.POST, null, files, null);
if (httpResponse.isSuccess()) {
System.out.println("上傳成功");
}
}
3.提交數(shù)據(jù)
public static void testRequest() {
String url = "http://127.0.0.1:12111/app.js";
Map<String, String> headers = new HashMap<>();
headers.put("content-type", "application/json");
String httpBody = "{\"name\":\"張三\"}";
HttpClient.Request(url, HttpMethod.POST, headers, httpBody, new onSimpleCallbackListener() {
@Override
public void onError(HttpResponse response, Exception e) {
e.printStackTrace();
System.out.println("response = [" + response + "], e = [" + e + "]");
}
@Override
public void onSuccess(HttpResponse response) throws Exception {
System.out.println("response = [" + response + "]");
}
});
}
4.同步請(qǐng)求
public static void testRequestSync() {
String url = "http://127.0.0.1:12111/app.js";
Map<String, String> headers = new HashMap<>();
headers.put("content-type", "application/json");
String httpBody = "{\"name\":\"張三\"}";
try {
HttpResponse response = HttpClient.RequestSync(url, HttpMethod.POST, headers, null, httpBody);
System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
}
}
5.文件下載,如果文件已存在,則用時(shí)間戳拼在文件名前面,通過DownloadFile的getOriginFileName()方法獲取瀏覽器返回文件名,如果是重定向獲取的文件下載十分有意義,不能用原始url判斷文件名。
public static void testDownloadFile() {
String downloadUrl = "http://file.itgowo.com/itgowo/RemoteDataController/web_app.zip";
String downloadDir = "temp";
HttpClient.RequestGetFile(downloadUrl, null, new onSimpleCallbackListener() {
@Override
public void onError(HttpResponse response, Exception e) {
e.printStackTrace();
System.out.println("response = [" + response + "], e = [" + e + "]");
}
@Override
public void onSuccess(HttpResponse response) throws Exception {
//下載文件不會(huì)觸發(fā)
System.out.println("response = [" + response + "]");
}
@Override
public void onSuccess(HttpResponse httpResponse, DownloadFile file) throws Exception {
file.saveToFile(downloadDir);
System.out.println("httpResponse = [" + httpResponse + "], file = [" + file.getFile() + "]");
}
@Override
public void onProcess(File file, int countBytes, int processBytes) throws Exception {
System.out.println("file = [" + file + "], countBytes = [" + countBytes + "], processBytes = [" + processBytes + "]");
}
});
}
6.同步方式下載文件,文件對(duì)象放在HttpResponse中的downloadFile里
public static void testSyncDownloadFile() {
try {
String url = "http://127.0.0.1:12111/app.js";
HttpResponse response = HttpClient.RequestSync(url, HttpMethod.GET, null, null);
System.out.println(response.getDownloadFile());
} catch (Exception e) {
e.printStackTrace();
}
}
六:說明
1. 回調(diào)接口onCallbackListener
- public void onError(HttpResponse response, Exception e)
發(fā)生錯(cuò)誤時(shí)回調(diào) |
|
HttpResponse |
請(qǐng)求結(jié)果,當(dāng)http狀態(tài)碼不是200系列時(shí),body可能包含錯(cuò)誤信息 |
Exception |
異常類 |
- public void onSuccess(HttpResponse response) throws Exception
非文件下載請(qǐng)求成功回調(diào) |
|
HttpRespons |
請(qǐng)求結(jié)果,當(dāng)http狀態(tài)碼是200系列時(shí)返回 |
- public void onSuccess(HttpResponse httpResponse, DownloadFile file) throws Exception
文件下載請(qǐng)求成功回調(diào) |
|
HttpResponse |
請(qǐng)求結(jié)果,downloadFile為下載文件類,同第二個(gè)參數(shù) |
DownloadFile |
下載文件類,此時(shí)只讀取了header信息,需要方法saveToFile(downloadDir)去保存文件 |
- public void onProcess(File file, int countBytes, int processBytes) throws Exception
下載文件時(shí):saveToFile(downloadDir)方法執(zhí)行后,觸發(fā)下載進(jìn)度;上傳文件時(shí):觸發(fā)上傳進(jìn)度 |
|
File |
下載文件或上傳文件 |
countBytes |
文件大小 |
processBytes |
文件大小 |
2. 請(qǐng)求方式
分為同步請(qǐng)求和異步請(qǐng)求,功能全部封裝到同步模塊,異步調(diào)用只是繼承封裝一層,此庫(kù)比較簡(jiǎn)單,按需繼承改造。
七:原理解析
- 以HttpURLConnection為基礎(chǔ)開發(fā),需要學(xué)會(huì)簡(jiǎn)單使用HttpURLConnection才能更好理解這個(gè)庫(kù)。
- 最核心請(qǐng)求類是RequestClient,封裝了request()方法開始請(qǐng)求,request()執(zhí)行先觸發(fā)prepare(RequestClient requestClient)方法,初始化請(qǐng)求參數(shù)。例如:
public static HttpResponse RequestSync(String url, HttpMethod method, Map<String, String> headers1, List<File> uploadFiles1, String requestJson) throws Exception {
RequestClient requestClient = new RequestClient(url, method.getMethod(), timeout, new onSimpleCallbackListener()) {
@Override
protected String prepare(RequestClient requestClient) {
if (headers1 != null) {
requestClient.addHeaders(headers1);
}
requestClient.setUploadFiles(uploadFiles1);
return requestJson;
}
};
return requestClient.request();
}
- 通過prepare()可以設(shè)置header和上傳文件和下載目錄等。返回值是String類型,就是請(qǐng)求的Body部分,通常的接口請(qǐng)求json文本就是放到這里,請(qǐng)求json文本就不要設(shè)置上傳文件了。如果是文件上傳,需要這樣定義:
protected String prepare(RequestClient requestClient)) {
if (headers1 != null) {
requestClient.addHeaders(headers1);
}
requestClient.setUploadFiles(uploadFiles1);
return null;
}
- 如果是文件下載,請(qǐng)求的body需不需要看你們接口定義,一般靜態(tài)資源請(qǐng)求是GET方法,body為null,可以這樣定義:
protected String prepare(RequestClient requestClient)) {
if (headers1 != null) {
requestClient.addHeaders(headers1);
}
return null;
}
- 如果用同步方法,只需要RequestClient用HttpResponse接收即可,如下:
RequestClient requestClient = new RequestClient(url, method.getMethod(), timeout, new onSimpleCallbackListener()) {};
return requestClient.request();
- 說說異步類RequestAsyncClient,其實(shí)只是實(shí)現(xiàn)了runnable接口,在run()方法中觸發(fā)request(),然后判斷執(zhí)行回調(diào),代碼如下:
public abstract class RequestAsyncClient extends RequestClient implements Runnable {
public RequestAsyncClient(String url, String method, int timeout, onCallbackListener listener) {
super(url, method, timeout, listener);
}
@Override
public void run() {
try {
request();
if (httpResponse.isSuccess()) {
if (httpResponse.isDownloadFile()) {
listener.onSuccess(httpResponse, httpResponse.getDownloadFile());
} else {
listener.onSuccess(httpResponse);
}
} else {
listener.onError(httpResponse, new Exception("code:" + httpResponse.getResponseCode() + " msg:" + httpResponse.getResponseMessage()));
}
} catch (Exception e) {
listener.onError(httpResponse.setSuccess(false), e);
}
}
}
- 具體請(qǐng)求內(nèi)容請(qǐng)看代碼,其中有各種判斷解析,文件下載只認(rèn)application/octet-stream,這點(diǎn)算是不足。文件下載還需要注意,執(zhí)行success()回調(diào)不代表文件下載完了,在返回的DownloadFile對(duì)象中封裝了輸入流,需要執(zhí)行saveToFile(下載目錄)才能真正保存到文件,saveToFile()方法也會(huì)觸發(fā)onProcess()進(jìn)度回調(diào)。
八:小期待
以下項(xiàng)目都是我圍繞遠(yuǎn)程控制寫的項(xiàng)目和子項(xiàng)目。都給star一遍吧。??
我的小站:IT狗窩
技術(shù)聯(lián)系QQ:1264957104