场景描述
在工作碰到这样一个需求:第三方平台的 API 要求POST请求,并且是 form-data 形式接收参数。
我编写 Java8 代码模拟 HTTP 客户端发送 POST form-data 形式的请求并传送字符串和数字参数。
准备工作
先写个服务器端接受 HTTP POST form-data 形式的参数:
package com.sing18.business.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/test")
public class TestController {
@PostMapping("/postFormData")
public Map<String, Object> postFormData(@RequestParam("param1") String param1,
@RequestParam("param2") Integer param2) {
Map<String, Object> result = new HashMap<>();
result.put("param1", param1);
result.put("param2", param2);
return result;
}
}
代码实现
接收HTTP返回数据的类 StrResponse
package zhangchao.common.http;
import java.util.List;
import java.util.Map;
/**
* 接收HTTP返回数据的对象
* @author zhangchao
*/
public class StrResponse {
private int code = 200;
private Map<String, List<String>> headers = null;
private String body = null;
public Map<String, List<String>> getHeaders() {
return headers;
}
public String getBody() {
return body;
}
public void setHeaders(Map<String, List<String>> headers) {
this.headers = headers;
}
public void setBody(String body) {
this.body = body;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getHeaderStr (String key) {
List<String> list = this.headers.get(key);
StringBuilder sb = new StringBuilder();
for (String str : list) {
sb.append(str);
}
return sb.toString();
}
public String getAllHeaderStr() {
if (null == headers || headers.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
for (String key : headers.keySet()) {
List<String> list = headers.get(key);
sb.append(key + ":\n");
for (String str : list) {
sb.append(" " + str + "\n");
}
}
return sb.toString();
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("StrResponse{");
sb.append("code=").append(code);
sb.append(", headers=").append(headers);
sb.append(", body='").append(body).append('\'');
sb.append('}');
return sb.toString();
}
}
统一发送HTTP请求的工具类 HttpUtils
package zhangchao.common.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 通用http发送方法
*
* @author zhangchao
*/
public class HttpUtils
{
public static StrResponse requestByte_responseStr(final String url, final String method,
final byte[] requestBody,final Map<String, String> headerMap, String responseEncoding) {
BufferedReader in = null;
BufferedReader errorReader = null;
HttpURLConnection connection = null;
StrResponse strResponse = null;
try {
StringBuilder result = new StringBuilder();
URL realUrl = new URL(url);
// 打开和URL之间的连接
connection = (HttpURLConnection) realUrl.openConnection();
connection.setRequestMethod(method);
// 请求内容的长度
if (null != requestBody && requestBody.length > 0) {
connection.setRequestProperty("Content-Length", String.valueOf(requestBody.length));
}
// 自定义请求头
if (null != headerMap && false == headerMap.isEmpty()) {
Set<String> keySet = headerMap.keySet();
for (String key : keySet) {
connection.setRequestProperty(key, headerMap.get(key));
}
}
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
// 把JSON作为字节流写入post请求的body中
connection.setDoOutput(true);
if (null != requestBody && requestBody.length > 0) {
connection.getOutputStream().write(requestBody);
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(), responseEncoding));
String line;
while ((line = in.readLine()) != null) {
result.append(line).append("\n");
}
strResponse = new StrResponse();
strResponse.setCode(connection.getResponseCode());
// 返回的header
Map<String, List<String>> map = connection.getHeaderFields();
strResponse.setHeaders(map);
// 返回的body
String responseBody = result.toString();
strResponse.setBody(responseBody);
} catch (Exception e) {
e.printStackTrace();
try {
if (null != connection) {
StringBuilder result = new StringBuilder();
// 定义 BufferedReader输入流来读取URL的响应
errorReader = new BufferedReader(new InputStreamReader(
connection.getErrorStream(), responseEncoding));
String line;
while ((line = errorReader.readLine()) != null) {
result.append(line).append("\n");
}
strResponse = new StrResponse();
strResponse.setCode(connection.getResponseCode());
// 返回的header
Map<String, List<String>> map = connection.getHeaderFields();
strResponse.setHeaders(map);
// 返回的body
String responseBody = result.toString();
strResponse.setBody(responseBody);
}
} catch (Exception e2) {
e2.printStackTrace();
}
} finally {
try {
if (null != in) {
in.close();
}
if (null != errorReader) {
errorReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return strResponse;
}
public static StrResponse requestStr_responseStr(final String url, final String method, final String requestBody,
final Map<String, String> headerMap, final String encoding) {
// 字符串转成字节流
byte[] bodyBytes = null;
try {
if (requestBody != null) {
bodyBytes = requestBody.getBytes(encoding);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return requestByte_responseStr(url, method, bodyBytes, headerMap, encoding);
}
}
具体发送 POST form-data 请求的类 TestPostFormData:
package zhangchao.postformdata;
import com.google.gson.Gson;
import zhangchao.common.http.HttpUtils;
import zhangchao.common.http.StrResponse;
import java.util.HashMap;
import java.util.Map;
public class TestPostFormData {
private static final String BOUNDARY = "------zhangchao";
public static void postFormData(final String token, final String param1, final Integer param2) {
String url = "http://localhost:13001/api/test/postFormData";
StringBuilder sb = new StringBuilder();
sb
.append("\r\n--").append(BOUNDARY)
.append("\r\nContent-Disposition: form-data; name=\"param1\"\r\n")
.append("\r\n").append(param1)
.append("\r\n--").append(BOUNDARY)
.append("\r\nContent-Disposition: form-data; name=\"param2\"\r\n")
.append("\r\n").append(param2)
.append("\r\n--").append(BOUNDARY).append("--");
String requestBody = sb.toString();
Map<String, String> headerMap = new HashMap<>();
headerMap.put("User-Agent", "PostmanRuntime/7.28.4");
headerMap.put("Accept", "*/*");
headerMap.put("Host", "localhost:13001");
headerMap.put("authorization", token);
headerMap.put("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
headerMap.put("Content-Length", "" + requestBody.getBytes().length);
StrResponse strResponse = HttpUtils.requestStr_responseStr(url, "POST", requestBody,
headerMap, "UTF-8");
if (strResponse == null || strResponse.getCode() != 200) {
return;
}
String body = strResponse.getBody();
System.out.println(body);
}
public static void main(String[] args) {
postFormData("youtoken", "sdsd_2", 2);
}
}
输出结果:
{"param1":"sdsd_2","param2":2}