使用工具:idea
框架:gradle、springboot
實現目標:使用 httpclient 發送文件/參數/json對象
method:post
主要用到的jar包:
compile group: 'net.sf.json-lib', name: 'json-lib', version: '2.4', classifier: 'jdk15'
//httpclient
// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime
compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.3'
// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore
compile group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.6'
花了大半天終於寫完這個測試類,能正常跑起來,下面主要貼出來兩種 httpclient 的發送和接收,基本夠用
特別注意:
1.文件和json對象是不能一起發送的,要發也是把json對象toString一下,見第一個方法
2.發送json對象,並用Requestbody接收,這種智能發對象,不能發文件,見第二個方法
預備幾個方法,因爲模擬數據用到的一樣,所以先貼這幾個公用方法:
//模擬文件數據,這裏自己改成自己的文件就可以了
private static List<Map<String, Object>> getFileList() {
//文件列表,搞了三個本地文件
List<Map<String, Object>> fileList = new ArrayList<>();
Map<String, Object> filedetail1 = new HashMap<>();
filedetail1.put("location", "F:\\me\\photos\\動漫\\3ba39425fec1965f4d088d2f.bmp");
filedetail1.put("fileName", "圖片1");
fileList.add(filedetail1);
Map<String, Object> filedetail2 = new HashMap<>();
filedetail2.put("location", "F:\\me\\photos\\動漫\\09b3970fd3f5cc65b1351da4.bmp");
filedetail2.put("fileName", "圖片2");
fileList.add(filedetail2);
Map<String, Object> filedetail3 = new HashMap<>();
filedetail3.put("location", "F:\\me\\photos\\動漫\\89ff57d93cd1b72cd0164ec9.bmp");
filedetail3.put("fileName", "圖片3");
fileList.add(filedetail3);
return fileList;
}
//模擬json對象數據
private static JSONObject getJsonObj() {
/**
* 這裏搞json對象方法很多
* 1.直接字符串貼過來,然後解析成json
* 2.用map<String,Object>,做好數據之後解析成json,.toJSONString
* 3.new 一個JSONObject對象,然後自己拼接
* 下面的例子用map好了,這個應該通俗易懂
*/
Map<String, Object> main = new HashMap<>();
main.put("token", "httpclient with file stringParam jsonParam and jasonArrayParam");
List<Map<String, Object>> contentList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
Map<String, Object> content = new HashMap<>();
content.put("id", i);
content.put("name", "數據" + i);
contentList.add(content);
}
main.put("content", contentList);
JSONObject jsonObject = JSONObject.fromObject(main);
System.out.println("jsonObject:" + jsonObject);
// //json字符串,去網上格式化一下,直接貼過來,然後解析成json
// String jsonString = "{\n" +
// " \"token\": \"stream data\", \n" +
// " \"content\": [\n" +
// " {\n" +
// " \"id\": \"1\", \n" +
// " \"name\": \"3ba39425fec1965f4d088d2f.bmp\"\n" +
// " }, \n" +
// " {\n" +
// " \"id\": \"2\", \n" +
// " \"name\": \"09b3970fd3f5cc65b1351da4.bmp\"\n" +
// " }, \n" +
// " {\n" +
// " \"id\": \"3\", \n" +
// " \"name\": \"89ff57d93cd1b72cd0164ec9.bmp\"\n" +
// " }\n" +
// " ]\n" +
// "}";
// JSONObject jsonObject = JSONObject.parseObject(jsonString);
return jsonObject;
}
//模擬json數組數據
private static JSONArray getJsonArray() {
List<Map<String, Object>> contentList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
Map<String, Object> content = new HashMap<>();
content.put("id", i);
content.put("name", "array數據" + i);
contentList.add(content);
}
JSONArray jsonArray =JSONArray.fromObject(contentList);
System.out.println("jsonArray:" + jsonArray);
return jsonArray;
}
主函數:
/**
* 主函數
* @param args
* @throws Exception
*/
public static void main(String args[]) throws Exception {
//模擬流文件及參數上傳
// testStreamUpload();
//httpClient模擬文件上傳
testFileParamUpload();
//httpClient模擬發送json對象,用JSONObject接收
testJSONObjectUpload();
}
/**
* httpClient模擬文件上傳
*/
static void testFileParamUpload() {
String url = "http://127.0.0.1:8090/kty/test/receiveHttpClientWithFile";
//json字符串,模擬了一個,傳圖片名字吧
Map<String, Object> param = new HashMap<>();
param.put("paramString", "i'm paramString!");
param.put("paramJSONObject", getJsonObj().toString());
param.put("paramJSONArray", getJsonArray().toString());
doPostFileAndParam(url, getFileList(), param);
}
/**
* 測試發送json對象並用json對象接收
*/
static void testJSONObjectUpload(){
String url = "http://127.0.0.1:8090/kty/test/receiveHttpClientJSONObject";
doPostJSONObject(url, getJsonObj(), getJsonArray());
}
文件和參數的 發送 和 接收 ,接收的時候要對應key value
testFileParamUpload
發送 httpClient 請求:
/**
* httpclient
* 發送文件和部分參數
*
* @return
*/
public static String doPostFileAndParam(String url, List<Map<String, Object>> fileList, Map<String, Object> param) {
String result = "";
//新建一個httpclient
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
//新建一個Post請求
HttpPost httppost = new HttpPost(url);
//新建文件對象
MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
ContentType contentType = ContentType.create("text/plain", "UTF-8");
//添加參數的時候,可以都使用addPart,然後new一個對象StringBody、FileBody、BinaryBody等
reqEntity
//設置編碼,這兩個一定要加,不然文件的文件名是中文就會亂碼
.setCharset(Charset.forName("utf-8"))
//默認是STRICT模式,用這個就不能使用自定義的編碼了
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)//也可以使用reqEntity.setLaxMode();具體的可以查看MultipartEntityBuilder類
//這個方法其實就是addPart(name, new StringBody(text, contentType));
.addTextBody("paramString", param.get("paramString").toString())
//textbody傳送的都是String類型,所以接收只能用string接收,接收後轉成json對象就可以了(後面一種方法直接可以用JSONObject接收,不論參數名)
.addTextBody("paramJSONObject", param.get("paramJSONObject").toString(), ContentType.APPLICATION_JSON)
.addTextBody("paramJSONArray", param.get("paramJSONArray").toString(), ContentType.APPLICATION_JSON)
//如果contentType不夠用,可以自己定義
.addPart("paramPart", new StringBody("addPart你好", contentType));
//拼接文件類型
for (Map<String, Object> elem : fileList) {//拼接參數
String location = elem.get("location").toString();
String fileName = elem.get("fileName").toString();
System.out.println(fileName);
File file = new File(location);
//添加二進制內容,這個方法可以放流進去,也可以放文件對象進去,很方便
InputStream fileStream = new FileInputStream(file);
reqEntity.addBinaryBody("file", fileStream, ContentType.APPLICATION_OCTET_STREAM, fileName);
//文件的Contenttype貌似只要合理就行,流、form_data、或者乾脆不填
// reqEntity.addBinaryBody("file", file, ContentType.APPLICATION_OCTET_STREAM, fileName);
//也可以用addPart添加
// reqEntity.addPart("file", new FileBody(file));
}
//將數據設置到post請求裏
httppost.setEntity(reqEntity.build());
//執行提交
System.err.println("執行請求:" + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
//獲得返回參數
InputStream is = response.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
System.out.println("收到的返回:" + result);
//關閉返回
response.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//關閉httpclient
httpclient.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
接收:
/**
* httpclient 接收文件
* 文件需要從request裏解析,可以自己手動解析,也可以像我這樣直接用multirequest接收,然後用getFiles就能拿到文件
* 其他參數String類型
*
* @return
* @RequestBody 加了這個才能區分,不然默認都是String的key value格式,會報mismatch arguments
*/
@PostMapping("/receiveHttpClientWithFile")
public String receiveHttpClientWithFile(
MultipartHttpServletRequest multiRequest, String paramString, String paramPart,
String paramJSONObject, String paramJSONArray) {
String result = "成功收到請求";
System.out.println("收到請求,開始執行");
System.out.println("paramString===" + paramString);
System.out.println("paramPart===" + paramPart);
//這裏就可以解析string爲json對象
System.out.println("paramJSONObject===" + paramJSONObject);
JSONObject resJsonObj = JSONObject.fromObject(paramJSONObject);
System.out.println("json對象裏的第一個元素token===" + resJsonObj.get("token"));
//這裏就可以解析string爲jsonarray數組
System.out.println("paramJSONArray===" + paramJSONArray);
JSONArray resJsonArray = JSONArray.fromObject(paramJSONArray);
System.out.println(resJsonArray.get(1));
List<MultipartFile> fileList = multiRequest.getFiles("file");
for (MultipartFile elem : fileList) {
System.out.println(elem.getOriginalFilename());
System.out.println("file===" + elem.getOriginalFilename() + "--" + elem.getSize() + elem.getContentType());
}
return result;
}
請求輸出:
接收輸出:
json對象的 發送 和 接收 ,接收方用 @RequestBody,無視對應key
testJSONObjectUpload()
發送 httpClient :
/**
* httpclient
* 發送json對象
* StringEntity可以直接用JSONObject接收
*
* @return
*/
public static String doPostJSONObject(String url, JSONObject jsonObject, JSONArray jsonArray) {
String result = "";
//新建一個httpclient
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
//新建一個Post請求
HttpPost httppost = new HttpPost(url);
//新建json對象
StringEntity stringEntity = new StringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON);
// StringEntity stringEntity = new StringEntity(jsonArray.toJSONString(), ContentType.APPLICATION_JSON);
//將數據設置到post請求裏
httppost.setEntity(stringEntity);
//執行提交
System.err.println("執行請求:" + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
//獲得返回參數
InputStream is = response.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
System.out.println("收到的返回:" + result);
//關閉返回
response.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//關閉httpclient
httpclient.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
接收:
/**
* httpclient 接收json對象
*
* @return
*/
@PostMapping("/receiveHttpClientJSONObject")
public String receiveHttpClientJSONObject(@RequestBody JSONObject param) {
String result = "成功收到請求";
System.out.println("收到請求,開始執行");
System.out.println("param===" + param);
System.out.println("json對象裏的第一個元素token===" + param.get("token"));
return result;
}
發送方控制檯打印:
接收方控制檯打印:
————————————————————————————————————————
綜上,代碼原文鏈接:https://blog.csdn.net/akxj2022/article/details/88691698
————————————————————————————————————————