使用Apache HttpClient 4.x进行进行一次Http请求
依赖
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.7</version>
</dependency>
请求式样
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpStatus;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import java.io.IOException;public class HttpPostUtils {/*** @param uri the request address* @param json the request data that must be a JSON string* @throws IOException if HTTP connection can not opened or closed successfully* @throws ParseException if response data can not be parsed successfully*/public String retryPostJson(String uri, String json) throws IOException, ParseException {if (StringUtils.isAnyBlank(uri, json)) {return null;}// 构建HttpClientCloseableHttpClient client = HttpClients.custom().setRetryHandler(new RetryHandler()).build();// 构建请求HttpPost httpPost = new HttpPost(uri);// 设置请求体StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);httpPost.setEntity(entity);// 设置超时时间RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(5000) // 超5秒还没返回新的可用链接,抛ConnectionPoolTimeoutException。默认值为0,表示无限等待。.setConnectTimeout(5000) // 超5秒还没建立链接,抛ConnectTimeoutException。默认值为0,表示无限等待。.setSocketTimeout(5000) // 超5秒还没返回数据,抛SocketTimeoutException。默认值为0,表示无限等待。.build();httpPost.setConfig(config);// ResponseCloseableHttpResponse response = null;String responseContent = null;try {response = client.execute(httpPost, HttpClientContext.create());if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {responseContent = EntityUtils.toString(response.getEntity(), Consts.UTF_8.name());}} finally {if (response != null) {response.close();}if (client != null) {client.close();}}return responseContent;}
}
失败重试机制
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.protocol.HttpContext;import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;public class RetryHandler implements HttpRequestRetryHandler {@Overridepublic boolean retryRequest(IOException exception, int executionCount, HttpContext context) {if (executionCount >= 2) {// 如果已经重试了2次,就放弃// Do not retry if over max retry countreturn false;}if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试return true;}if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常return false;}if (exception instanceof SSLException) {// SSL握手异常// SSL handshake exceptionreturn false;}if (exception instanceof ConnectTimeoutException) {// 连接被拒绝return false;}if (exception instanceof InterruptedIOException) {// An input or output transfer has been terminated// 超时return false;}if (exception instanceof UnknownHostException) {// Unknown host 修改代码让不识别主机时重试,实际业务当不识别的时候不应该重试,再次为了演示重试过程,执行会显示retryCount次下面的输出// 目标服务器不可达System.out.println("不识别主机重试");return true;}if (exception instanceof ConnectException) {// Connection refusedreturn false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();if (!(request instanceof HttpEntityEnclosingRequest)) {// Retry if the request is considered idempotentreturn true;}return false;}
}
模拟解析返回的Json串
public static List<User> parserJsonToUser() {// 模拟返回的Json串Map<String, List<String>> map = new HashMap<>();map.put("name", Arrays.asList("name1", "name2", "name3"));map.put("age", Arrays.asList("11", "23", "23"));map.put("num", Arrays.asList("123", "234", "345"));String json1 = JsonUtils.toJson(map);System.out.println(json1);// fastjsonJSONObject jsonObject = JSON.parseObject(json1, Feature.OrderedField);// 返回的属性List<String> fields = new ArrayList<>(map.keySet());// 几份值int size = jsonObject.getJSONArray(fields.get(0)).size();List<User> users = new ArrayList<>();for (int i = 0; i < size; i++) {User user1 = new User();for (String field : fields) {Object value = jsonObject.getJSONArray(field).get(i);ReflectUtils.setFieldValue(user1, field, value);}users.add(user1);}System.out.println(users);return users;
}结果
{"num":["123","234","345"],"name":["name1","name2","name3"],"age":["11","23","23"]}
[HttpPostUtils.User(name=name1, age=11, num=123), HttpPostUtils.User(name=name2, age=23, num=234), HttpPostUtils.User(name=name3, age=23, num=345)]
参考
使用Apache HttpClient 4.x进行异常重试
Need 学习消化
二十六、CloseableHttpClient的使用和优化