• 通用HttpClient封装


    一、封装通用HttpClient,兼容Http/Https接口调用,方便业务层交互使用.

    二、使用Pom文件如下:

    1. org.projectlombok
    2. lombok
    3. 1.18.2
    4. provided
    5. org.apache.commons
    6. commons-lang3
    7. 3.12.0
    8. org.apache.commons
    9. commons-collections4
    10. 4.4
    11. org.apache.httpcomponents
    12. httpclient
    13. 4.5.6

     三、HttpClient封装诉求如下.

    ①、兼容Http/Https,目前采用跳过证书校验.

    ②、基于HttpClient连接池化以及过期、空闲连接清理.

    ③、各种超时时间设置以及重试策略.

    ④、简单易用,方便扩展和维护,减低使用配置.

    ⑤、其他j微服务调用可在此基础上封装XXXClient只需要一些鉴权和url参数就可以快速对接使用.

    1. package com.boot.skywalk;
    2. import lombok.Data;
    3. /**
    4. * 通用响应
    5. */
    6. @Data
    7. public class HttpResult {
    8. /**
    9. * 响应的状态码
    10. */
    11. private int code;
    12. /**
    13. * 响应体
    14. */
    15. private String body;
    16. }
    1. package com.boot.skywalk.exception;
    2. /**
    3. * 全局异常
    4. */
    5. public class GlobalException extends RuntimeException {
    6. public GlobalException(){
    7. super();
    8. }
    9. public GlobalException(String message){
    10. super(message);
    11. }
    12. public GlobalException(Throwable cause){
    13. super(cause);
    14. }
    15. public GlobalException(String message,Throwable cause) {
    16. super(message, cause);
    17. }
    18. }

    RestClient封装如下:代码比较简单 

    1. package com.boot.skywalk;
    2. import com.alibaba.fastjson.JSON;
    3. import com.boot.skywalk.exception.GlobalException;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.apache.commons.collections4.CollectionUtils;
    6. import org.apache.commons.collections4.MapUtils;
    7. import org.apache.commons.lang3.StringUtils;
    8. import org.apache.http.HttpEntity;
    9. import org.apache.http.HttpEntityEnclosingRequest;
    10. import org.apache.http.HttpRequest;
    11. import org.apache.http.NameValuePair;
    12. import org.apache.http.client.HttpRequestRetryHandler;
    13. import org.apache.http.client.config.RequestConfig;
    14. import org.apache.http.client.entity.UrlEncodedFormEntity;
    15. import org.apache.http.client.methods.CloseableHttpResponse;
    16. import org.apache.http.client.methods.HttpDelete;
    17. import org.apache.http.client.methods.HttpGet;
    18. import org.apache.http.client.methods.HttpPost;
    19. import org.apache.http.client.methods.HttpPut;
    20. import org.apache.http.client.protocol.HttpClientContext;
    21. import org.apache.http.client.utils.URIBuilder;
    22. import org.apache.http.config.Registry;
    23. import org.apache.http.config.RegistryBuilder;
    24. import org.apache.http.conn.ConnectTimeoutException;
    25. import org.apache.http.conn.HttpClientConnectionManager;
    26. import org.apache.http.conn.socket.ConnectionSocketFactory;
    27. import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    28. import org.apache.http.conn.ssl.NoopHostnameVerifier;
    29. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    30. import org.apache.http.entity.StringEntity;
    31. import org.apache.http.impl.client.CloseableHttpClient;
    32. import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
    33. import org.apache.http.impl.client.HttpClients;
    34. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    35. import org.apache.http.message.BasicNameValuePair;
    36. import org.apache.http.protocol.HttpContext;
    37. import org.apache.http.util.EntityUtils;
    38. import javax.net.ssl.SSLContext;
    39. import javax.net.ssl.SSLException;
    40. import javax.net.ssl.TrustManager;
    41. import javax.net.ssl.X509TrustManager;
    42. import java.io.BufferedReader;
    43. import java.io.Closeable;
    44. import java.io.IOException;
    45. import java.io.InterruptedIOException;
    46. import java.net.URISyntaxException;
    47. import java.net.UnknownHostException;
    48. import java.nio.charset.Charset;
    49. import java.nio.charset.StandardCharsets;
    50. import java.security.KeyManagementException;
    51. import java.security.NoSuchAlgorithmException;
    52. import java.security.cert.CertificateException;
    53. import java.util.ArrayList;
    54. import java.util.HashMap;
    55. import java.util.List;
    56. import java.util.Map;
    57. import java.util.Objects;
    58. import java.util.concurrent.TimeUnit;
    59. /**
    60. * Http通用:RestClient
    61. */
    62. @Slf4j
    63. public final class RestClient {
    64. private static final RestClient INSTANCE = new RestClient();
    65. /**
    66. * 建立连接时间
    67. */
    68. private static final int CONNECTION_TIME = 3000;
    69. /**
    70. * 发送请求时间
    71. */
    72. private static final int CONNECTION_REQUEST_TIME = 30000;
    73. /**
    74. * 读取数据时间
    75. */
    76. private static final int SOCKET_TIME = 180000;
    77. /**
    78. * 重试次数
    79. */
    80. private static final int RETRY = 3;
    81. /**
    82. * 请求类型:FORM表单
    83. */
    84. private static final String REQUEST_TYPE_FORM = "application/x-www-form-urlencoded; charset=UTF-8";
    85. /**
    86. * 请求类型:JSON体
    87. */
    88. private static final String REQUEST_TYPE_JSON = "application/json; charset=utf-8";
    89. private RestClient() {
    90. }
    91. /**
    92. * Http Get:不带请求参数
    93. *
    94. * @param url url
    95. * @param headerMap headerMap
    96. * @return String
    97. */
    98. public String get(String url, Map headerMap) {
    99. return get(url, headerMap, null);
    100. }
    101. /**
    102. * Http Get:带请求参数
    103. *
    104. * @param url url
    105. * @param headerMap headerMap
    106. * @param params params
    107. * @return String
    108. */
    109. public String get(String url, Map headerMap, Map params) {
    110. checkUrl(url);
    111. checkHeader(headerMap);
    112. return doGet(url, headerMap, params, StandardCharsets.UTF_8);
    113. }
    114. /**
    115. * Http Post:Form表单不带请求参数
    116. *
    117. * @param url URL
    118. * @param headerMap headerMap
    119. * @return String
    120. */
    121. public String post(String url, Map headerMap) {
    122. return doPostForForm(url, headerMap, null, StandardCharsets.UTF_8);
    123. }
    124. /**
    125. * Http Post:根据请头识别FORM表单还是JSON体
    126. *
    127. * @param url url
    128. * @param map map
    129. * @return String
    130. */
    131. public String post(String url, Map headerMap, Map map) {
    132. checkUrl(url);
    133. checkHeader(headerMap);
    134. checkBody(map);
    135. String contentType = (String) headerMap.get("Content-type");
    136. if (REQUEST_TYPE_FORM.equalsIgnoreCase(contentType)) {
    137. return doPostForForm(url, headerMap, map, StandardCharsets.UTF_8);
    138. } else if (REQUEST_TYPE_JSON.equalsIgnoreCase(contentType)) {
    139. return doPostForJson(url, headerMap, map, StandardCharsets.UTF_8);
    140. } else {
    141. log.error("not support this post type");
    142. throw new GlobalException("not support this post type");
    143. }
    144. }
    145. /**
    146. * HTTP Put:Form表单方式不带参数
    147. * Content-type:application/x-www-form-urlencoded; charset=UTF-8
    148. * @param url url
    149. * @param headerMap headerMap
    150. * @return String
    151. */
    152. public static String put(String url, Map headerMap) {
    153. checkUrl(url);
    154. checkHeader(headerMap);
    155. return doPut(url, headerMap, null);
    156. }
    157. /**
    158. * Http Delete:不带参数的表单形式
    159. * Content-type:application/x-www-form-urlencoded; charset=UTF-8
    160. * @param url url
    161. * @param headerMap header
    162. * @return HttpResult
    163. */
    164. public static String delete(String url, Map headerMap){
    165. checkUrl(url);
    166. checkHeader(headerMap);
    167. return doDelete(url, headerMap, null);
    168. }
    169. /**
    170. * HTTP Get:带请求参数
    171. *
    172. * @param url 请求的url地址 ?之前的地址
    173. * @param headerMap 请求头
    174. * @param params 请求的参数
    175. * @param charset 编码格式
    176. * @return String
    177. */
    178. public static String doGet(String url, Map headerMap, Map params, Charset charset) {
    179. StringBuffer resultBuffer = null;
    180. BufferedReader bufferedReader = null;
    181. CloseableHttpResponse response = null;
    182. URIBuilder uriBuilder = null;
    183. String result = null;
    184. try {
    185. uriBuilder = new URIBuilder(url);
    186. if(MapUtils.isNotEmpty(params)) {
    187. for (Map.Entry entry : params.entrySet()) {
    188. uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
    189. }
    190. }
    191. HttpGet httpGet = new HttpGet(uriBuilder.build());
    192. headerMap.forEach((key, value) -> {
    193. httpGet.addHeader(key, value.toString());
    194. });
    195. response = httpClient().execute(httpGet);
    196. if (Objects.nonNull(response.getEntity())) {
    197. result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
    198. }
    199. } catch (URISyntaxException e) {
    200. log.error("url synctax error", e);
    201. } catch (Exception e) {
    202. log.error("execute get request error", e);
    203. } finally {
    204. close(response);
    205. }
    206. return result;
    207. }
    208. /**
    209. * HTTP Post:Form表单方式
    210. * Content-type:application/x-www-form-urlencoded; charset=UTF-8
    211. *
    212. * @param url 请求的url地址?之前的地址
    213. * @param headerMap 请求头的参数
    214. * @param paramMap 请求的参数
    215. * @param charset 编码格式
    216. * @return String
    217. */
    218. public static String doPostForForm(String url, Map headerMap, Map paramMap, Charset charset) {
    219. List pairs = null;
    220. CloseableHttpResponse response = null;
    221. String result = null;
    222. pairs = new ArrayList<>(paramMap.size());
    223. for (Map.Entry entry : paramMap.entrySet()) {
    224. if (entry.getValue() != null) {
    225. pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
    226. }
    227. }
    228. HttpPost httpPost = new HttpPost(url);
    229. headerMap.forEach((key, value) -> {
    230. httpPost.setHeader(key, value.toString());
    231. });
    232. if (CollectionUtils.isNotEmpty(pairs)) {
    233. httpPost.setEntity(new UrlEncodedFormEntity(pairs, charset));
    234. }
    235. try {
    236. response = httpClient().execute(httpPost);
    237. HttpEntity entity = response.getEntity();
    238. if (entity != null) {
    239. result = EntityUtils.toString(entity, charset);
    240. }
    241. } catch (Exception e) {
    242. log.error("execute post request error", e);
    243. } finally {
    244. close(response);
    245. }
    246. return result;
    247. }
    248. /**
    249. * HTTP Post:JSON形式
    250. * Content-type:application/json; charset=utf-8
    251. *
    252. * @param url 请求的url地址?之前的地址
    253. * @param headerMap 请求头的参数
    254. * @param bodyMap 请求的参数
    255. * @param charset 编码格式
    256. * @return String
    257. */
    258. public static String doPostForJson(String url, Map headerMap, Map bodyMap, Charset charset) {
    259. CloseableHttpResponse response = null;
    260. String result = null;
    261. HttpPost httpPost = new HttpPost(url);
    262. // Body参数设置到请求体中
    263. httpPost.setEntity(new StringEntity(JSON.toJSONString(bodyMap), charset));
    264. headerMap.forEach((key, value) -> {
    265. httpPost.setHeader(key, value.toString());
    266. });
    267. try {
    268. response = httpClient().execute(httpPost);
    269. HttpEntity entity = response.getEntity();
    270. if (entity != null) {
    271. result = EntityUtils.toString(entity, charset);
    272. }
    273. } catch (Exception e) {
    274. log.error("execute post request error", e);
    275. } finally {
    276. close(response);
    277. }
    278. return result;
    279. }
    280. /**
    281. * HTTP Put:Form表单方式带参数
    282. * Content-type:application/x-www-form-urlencoded; charset=UTF-8
    283. *
    284. * @param url url
    285. * @param headerMap headerMap
    286. * @param paramMap paramMap
    287. * @return String
    288. */
    289. public static String doPut(String url, Map headerMap, Map paramMap) {
    290. HttpPut httpPut = new HttpPut(url);
    291. String result = null;
    292. CloseableHttpResponse response = null;
    293. List parameters = new ArrayList<>();
    294. if (MapUtils.isNotEmpty(paramMap)) {
    295. for (Map.Entry entry : paramMap.entrySet()) {
    296. parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
    297. }
    298. }
    299. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8);
    300. httpPut.setEntity(entity);
    301. headerMap.forEach((key, value) -> {
    302. httpPut.setHeader(key, value.toString());
    303. });
    304. try {
    305. response = httpClient().execute(httpPut);
    306. int code = response.getStatusLine().getStatusCode();
    307. if (response.getEntity() != null) {
    308. result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
    309. }
    310. } catch (IOException e) {
    311. log.error("io error", e);
    312. } catch (Exception e) {
    313. log.error("execute put request error", e);
    314. } finally {
    315. close(response);
    316. }
    317. return result;
    318. }
    319. /**
    320. * Http Delete:不带参数的表单形式
    321. * Content-type:application/x-www-form-urlencoded; charset=UTF-8
    322. * @param url url
    323. * @param headerMap headerMap
    324. * @param paramMap paramMap
    325. * @return String
    326. */
    327. public static String doDelete(String url, Map headerMap, Map paramMap) {
    328. URIBuilder uriBuilder = null;
    329. String result = null;
    330. CloseableHttpResponse response = null;
    331. try {
    332. uriBuilder = new URIBuilder(url);
    333. if (MapUtils.isNotEmpty(paramMap)) {
    334. for (Map.Entry entry : paramMap.entrySet()) {
    335. uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
    336. }
    337. }
    338. HttpDelete httpDelete = new HttpDelete(uriBuilder.build());
    339. headerMap.forEach((key, value) -> {
    340. httpDelete.setHeader(key, value.toString());
    341. });
    342. response = httpClient().execute(httpDelete);
    343. int code = response.getStatusLine().getStatusCode();
    344. if (Objects.nonNull(response.getEntity())) {
    345. result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
    346. }
    347. } catch (URISyntaxException e) {
    348. log.error("url synctax error", e);
    349. } catch (Exception e) {
    350. log.error("execute post request error", e);
    351. } finally {
    352. close(response);
    353. }
    354. return result;
    355. }
    356. public static RestClient getInstance() {
    357. return INSTANCE;
    358. }
    359. /**
    360. * 忽略证书验证的CloseableHttpClient对象,适配Http/Https
    361. *
    362. * @return CloseableHttpClient
    363. */
    364. public static CloseableHttpClient httpClient() {
    365. CloseableHttpClient closeableHttpClient = null;
    366. try {
    367. SSLContext sc = SSLContext.getInstance("SSL");
    368. sc.init(null, getTrustingManager(), new java.security.SecureRandom());
    369. // 使用上面的策略初始化上下文
    370. SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sc,
    371. new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
    372. closeableHttpClient = HttpClients.custom()
    373. // 设置超时时间
    374. .setDefaultRequestConfig(getRequestConfig())
    375. // 设置连接池
    376. .setConnectionManager(getPoolingManager())
    377. // 设置重试策略,框架层面重试,可以在业务层面重试
    378. //.setRetryHandler(getRetryHandler())
    379. .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
    380. // 连接池清理过期连接
    381. .evictExpiredConnections()
    382. // 连接池释放空闲连接
    383. .evictIdleConnections(60, TimeUnit.SECONDS)
    384. .build();
    385. } catch (KeyManagementException e) {
    386. log.error("KeyManagement error", e);
    387. } catch (NoSuchAlgorithmException e) {
    388. log.error("No Such Algorithm error", e);
    389. }
    390. return closeableHttpClient;
    391. }
    392. /**
    393. * 信任所有证书
    394. *
    395. * @return TrustManager[]
    396. */
    397. private static TrustManager[] getTrustingManager() {
    398. TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
    399. @Override
    400. public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {
    401. }
    402. @Override
    403. public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {
    404. }
    405. @Override
    406. public java.security.cert.X509Certificate[] getAcceptedIssuers() {
    407. return null;
    408. }
    409. }};
    410. return trustAllCerts;
    411. }
    412. /**
    413. * Http连接池配置
    414. *
    415. * @return HttpClientConnectionManager
    416. */
    417. public static HttpClientConnectionManager getPoolingManager() throws NoSuchAlgorithmException, KeyManagementException {
    418. SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    419. sslContext.init(null, null, null);
    420. SSLContext.setDefault(sslContext);
    421. Registry socketFactoryRegistry =
    422. RegistryBuilder.create()
    423. .register("http", PlainConnectionSocketFactory.INSTANCE)
    424. .register("https", new SSLConnectionSocketFactory(sslContext)).build();
    425. PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
    426. // 设置整个连接池最大连接数
    427. connectionManager.setMaxTotal(200);
    428. // 最大路由
    429. connectionManager.setDefaultMaxPerRoute(10);
    430. return connectionManager;
    431. }
    432. /**
    433. * 封装RequestConfig
    434. *
    435. * @return RequestConfig
    436. */
    437. public static RequestConfig getRequestConfig() {
    438. RequestConfig requestConfig = RequestConfig.custom().
    439. setConnectTimeout(getConnectionTime()).
    440. setConnectionRequestTimeout(getConnectionRequestTime())
    441. .setSocketTimeout(getSocketTime()).build();
    442. return requestConfig;
    443. }
    444. /**
    445. * HttpClient的重试策略
    446. *
    447. * @return HttpRequestRetryHandler
    448. */
    449. public static HttpRequestRetryHandler getRetryHandler() {
    450. HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {
    451. public boolean retryRequest(
    452. IOException exception,
    453. int executionCount,
    454. HttpContext context) {
    455. // 重试三次
    456. if (executionCount >= RETRY) {
    457. return false;
    458. }
    459. if (exception instanceof InterruptedIOException) {
    460. // 超时
    461. return false;
    462. }
    463. if (exception instanceof UnknownHostException) {
    464. // 目标服务器不可达
    465. return false;
    466. }
    467. if (exception instanceof ConnectTimeoutException) {
    468. // 连接被拒绝
    469. return false;
    470. }
    471. if (exception instanceof SSLException) {
    472. // SSL握手异常
    473. return false;
    474. }
    475. HttpClientContext clientContext = HttpClientContext.adapt(context);
    476. HttpRequest request = clientContext.getRequest();
    477. boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
    478. if (idempotent) {
    479. // 如果请求是幂等的,就再次尝试
    480. return true;
    481. }
    482. return false;
    483. }
    484. };
    485. return retryHandler;
    486. }
    487. public static Integer getConnectionTime() {
    488. return CONNECTION_TIME;
    489. }
    490. public static Integer getConnectionRequestTime() {
    491. return CONNECTION_REQUEST_TIME;
    492. }
    493. public static Integer getSocketTime() {
    494. return SOCKET_TIME;
    495. }
    496. /**
    497. * 校验url,支持扩展
    498. *
    499. * @param url
    500. */
    501. private static void checkUrl(String url) {
    502. if (StringUtils.isBlank(url)) {
    503. log.error("rest client request url not null");
    504. throw new GlobalException("rest client request url not null");
    505. }
    506. }
    507. /**
    508. * 校验Header,支持扩展
    509. *
    510. * @param headerMap
    511. */
    512. private static void checkHeader(Map headerMap) {
    513. if (MapUtils.isEmpty(headerMap)) {
    514. log.error("rest client request header not null");
    515. throw new GlobalException("rest client request header not null");
    516. }
    517. }
    518. /**
    519. * 校验Body,支持扩展
    520. *
    521. * @param bodyMap
    522. */
    523. private static void checkBody(Map bodyMap) {
    524. if (MapUtils.isEmpty(bodyMap)) {
    525. log.error("rest client request param map not null");
    526. throw new GlobalException("rest client request map not null");
    527. }
    528. }
    529. /**
    530. * 关闭流资源
    531. *
    532. * @param closeable
    533. */
    534. private static void close(Closeable closeable) {
    535. try {
    536. closeable.close();
    537. } catch (IOException e) {
    538. log.error("close error", e);
    539. }
    540. }

    四、测试请求

    ①、Http+Get无参数

    1. String url="http://test.code.com/skywalk/test/log/filter";
    2. Map headerMap = new HashMap<>();
    3. headerMap.put("Content-type", "application/json; charset=utf-8");
    4. headerMap.put("Accept", "application/json");
    5. String string = RestClient.getInstance().get(url, headerMap);
    6. System.out.println(string);

     ②、Https接口+Post表单

    这里调用阿里云接口手机号码+IP归属地Https接口为例【云厂商目前都提供一些免费的Https接口供测试使用的,非常方便,这里使用AppCode鉴权】

    1. String url = "https://jmipquery3.market.alicloudapi.com/ip/query-v3/";
    2. Map headerMap = new HashMap<>();
    3. headerMap.put("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
    4. headerMap.put("Accept", "application/json");
    5. headerMap.put("Authorization", "APPCODE 你的code");
    6. Map bodyMap = new HashMap<>();
    7. bodyMap.put("ip", "117.173.222.90");
    8. String string = RestClient.getInstance().post(url, headerMap, bodyMap);
    9. System.out.println(string);

     ③、Https接口+Get带参数

    1. String url = "https://api04.aliyun.venuscn.com/mobile";
    2. Map headerMap = new HashMap<>();
    3. Map bodyMap = new HashMap<>();
    4. headerMap.put("Content-type", "text/html; charset=utf-8");
    5. headerMap.put("Accept", "application/json");
    6. headerMap.put("Authorization", "APPCODE 你的code");
    7. bodyMap.put("mobile", "18138434699");

     

    关于重试说明:

    ①、不重试写法:

    setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))

    ②、默认是重试三次

    1. public DefaultHttpRequestRetryHandler() {
    2. this(3, false);
    3. }

      ③、自定义重试策略,哪些异常需要,哪些异常不需要.

    1. public static HttpRequestRetryHandler getRetryHandler() {
    2. HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {
    3. public boolean retryRequest(
    4. IOException exception,
    5. int executionCount,
    6. HttpContext context) {
    7. // 重试三次
    8. if (executionCount >= RETRY) {
    9. return false;
    10. }
    11. if (exception instanceof InterruptedIOException) {
    12. // 超时
    13. return false;
    14. }
    15. if (exception instanceof UnknownHostException) {
    16. // 目标服务器不可达
    17. return false;
    18. }
    19. if (exception instanceof ConnectTimeoutException) {
    20. // 连接被拒绝
    21. return false;
    22. }
    23. if (exception instanceof SSLException) {
    24. // SSL握手异常
    25. return false;
    26. }
    27. HttpClientContext clientContext = HttpClientContext.adapt(context);
    28. HttpRequest request = clientContext.getRequest();
    29. boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
    30. if (idempotent) {
    31. // 如果请求是幂等的,就再次尝试
    32. return true;
    33. }
    34. return false;
    35. }
    36. };
    37. return retryHandler;
    38. }

    ④、业务层调用可以使用函数式接口或者while循环重试调用三次.

    更多业务参数参考这篇博客:HttpClient专题

    【附录HttpStatus】

     ①、Apache下HttpClient的HttpStatus。

    1. package org.apache.http;
    2. /**
    3. * Constants enumerating the HTTP status codes.
    4. * All status codes defined in RFC1945 (HTTP/1.0), RFC2616 (HTTP/1.1), and
    5. * RFC2518 (WebDAV) are listed.
    6. *
    7. * @see StatusLine
    8. * @since 4.0
    9. */
    10. public interface HttpStatus {
    11. // --- 1xx Informational ---
    12. /** {@code 100 Continue} (HTTP/1.1 - RFC 2616) */
    13. int SC_CONTINUE = 100;
    14. /** {@code 101 Switching Protocols} (HTTP/1.1 - RFC 2616)*/
    15. int SC_SWITCHING_PROTOCOLS = 101;
    16. /** {@code 102 Processing} (WebDAV - RFC 2518) */
    17. int SC_PROCESSING = 102;
    18. // --- 2xx Success ---
    19. /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
    20. int SC_OK = 200;
    21. /** {@code 201 Created} (HTTP/1.0 - RFC 1945) */
    22. int SC_CREATED = 201;
    23. /** {@code 202 Accepted} (HTTP/1.0 - RFC 1945) */
    24. int SC_ACCEPTED = 202;
    25. /** {@code 203 Non Authoritative Information} (HTTP/1.1 - RFC 2616) */
    26. int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    27. /** {@code 204 No Content} (HTTP/1.0 - RFC 1945) */
    28. int SC_NO_CONTENT = 204;
    29. /** {@code 205 Reset Content} (HTTP/1.1 - RFC 2616) */
    30. int SC_RESET_CONTENT = 205;
    31. /** {@code 206 Partial Content} (HTTP/1.1 - RFC 2616) */
    32. int SC_PARTIAL_CONTENT = 206;
    33. /**
    34. * {@code 207 Multi-Status} (WebDAV - RFC 2518)
    35. * or
    36. * {@code 207 Partial Update OK} (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?)
    37. */
    38. int SC_MULTI_STATUS = 207;
    39. // --- 3xx Redirection ---
    40. /** {@code 300 Mutliple Choices} (HTTP/1.1 - RFC 2616) */
    41. int SC_MULTIPLE_CHOICES = 300;
    42. /** {@code 301 Moved Permanently} (HTTP/1.0 - RFC 1945) */
    43. int SC_MOVED_PERMANENTLY = 301;
    44. /** {@code 302 Moved Temporarily} (Sometimes {@code Found}) (HTTP/1.0 - RFC 1945) */
    45. int SC_MOVED_TEMPORARILY = 302;
    46. /** {@code 303 See Other} (HTTP/1.1 - RFC 2616) */
    47. int SC_SEE_OTHER = 303;
    48. /** {@code 304 Not Modified} (HTTP/1.0 - RFC 1945) */
    49. int SC_NOT_MODIFIED = 304;
    50. /** {@code 305 Use Proxy} (HTTP/1.1 - RFC 2616) */
    51. int SC_USE_PROXY = 305;
    52. /** {@code 307 Temporary Redirect} (HTTP/1.1 - RFC 2616) */
    53. int SC_TEMPORARY_REDIRECT = 307;
    54. // --- 4xx Client Error ---
    55. /** {@code 400 Bad Request} (HTTP/1.1 - RFC 2616) */
    56. int SC_BAD_REQUEST = 400;
    57. /** {@code 401 Unauthorized} (HTTP/1.0 - RFC 1945) */
    58. int SC_UNAUTHORIZED = 401;
    59. /** {@code 402 Payment Required} (HTTP/1.1 - RFC 2616) */
    60. int SC_PAYMENT_REQUIRED = 402;
    61. /** {@code 403 Forbidden} (HTTP/1.0 - RFC 1945) */
    62. int SC_FORBIDDEN = 403;
    63. /** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */
    64. int SC_NOT_FOUND = 404;
    65. /** {@code 405 Method Not Allowed} (HTTP/1.1 - RFC 2616) */
    66. int SC_METHOD_NOT_ALLOWED = 405;
    67. /** {@code 406 Not Acceptable} (HTTP/1.1 - RFC 2616) */
    68. int SC_NOT_ACCEPTABLE = 406;
    69. /** {@code 407 Proxy Authentication Required} (HTTP/1.1 - RFC 2616)*/
    70. int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    71. /** {@code 408 Request Timeout} (HTTP/1.1 - RFC 2616) */
    72. int SC_REQUEST_TIMEOUT = 408;
    73. /** {@code 409 Conflict} (HTTP/1.1 - RFC 2616) */
    74. int SC_CONFLICT = 409;
    75. /** {@code 410 Gone} (HTTP/1.1 - RFC 2616) */
    76. int SC_GONE = 410;
    77. /** {@code 411 Length Required} (HTTP/1.1 - RFC 2616) */
    78. int SC_LENGTH_REQUIRED = 411;
    79. /** {@code 412 Precondition Failed} (HTTP/1.1 - RFC 2616) */
    80. int SC_PRECONDITION_FAILED = 412;
    81. /** {@code 413 Request Entity Too Large} (HTTP/1.1 - RFC 2616) */
    82. int SC_REQUEST_TOO_LONG = 413;
    83. /** {@code 414 Request-URI Too Long} (HTTP/1.1 - RFC 2616) */
    84. int SC_REQUEST_URI_TOO_LONG = 414;
    85. /** {@code 415 Unsupported Media Type} (HTTP/1.1 - RFC 2616) */
    86. int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    87. /** {@code 416 Requested Range Not Satisfiable} (HTTP/1.1 - RFC 2616) */
    88. int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    89. /** {@code 417 Expectation Failed} (HTTP/1.1 - RFC 2616) */
    90. int SC_EXPECTATION_FAILED = 417;
    91. /**
    92. * Static constant for a 418 error.
    93. * {@code 418 Unprocessable Entity} (WebDAV drafts?)
    94. * or {@code 418 Reauthentication Required} (HTTP/1.1 drafts?)
    95. */
    96. // not used
    97. // public static final int SC_UNPROCESSABLE_ENTITY = 418;
    98. /**
    99. * Static constant for a 419 error.
    100. * {@code 419 Insufficient Space on Resource}
    101. * (WebDAV - draft-ietf-webdav-protocol-05?)
    102. * or {@code 419 Proxy Reauthentication Required}
    103. * (HTTP/1.1 drafts?)
    104. */
    105. int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
    106. /**
    107. * Static constant for a 420 error.
    108. * {@code 420 Method Failure}
    109. * (WebDAV - draft-ietf-webdav-protocol-05?)
    110. */
    111. int SC_METHOD_FAILURE = 420;
    112. /** {@code 422 Unprocessable Entity} (WebDAV - RFC 2518) */
    113. int SC_UNPROCESSABLE_ENTITY = 422;
    114. /** {@code 423 Locked} (WebDAV - RFC 2518) */
    115. int SC_LOCKED = 423;
    116. /** {@code 424 Failed Dependency} (WebDAV - RFC 2518) */
    117. int SC_FAILED_DEPENDENCY = 424;
    118. /** {@code 429 Too Many Requests} (Additional HTTP Status Codes - RFC 6585) */
    119. int SC_TOO_MANY_REQUESTS = 429;
    120. // --- 5xx Server Error ---
    121. /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
    122. int SC_INTERNAL_SERVER_ERROR = 500;
    123. /** {@code 501 Not Implemented} (HTTP/1.0 - RFC 1945) */
    124. int SC_NOT_IMPLEMENTED = 501;
    125. /** {@code 502 Bad Gateway} (HTTP/1.0 - RFC 1945) */
    126. int SC_BAD_GATEWAY = 502;
    127. /** {@code 503 Service Unavailable} (HTTP/1.0 - RFC 1945) */
    128. int SC_SERVICE_UNAVAILABLE = 503;
    129. /** {@code 504 Gateway Timeout} (HTTP/1.1 - RFC 2616) */
    130. int SC_GATEWAY_TIMEOUT = 504;
    131. /** {@code 505 HTTP Version Not Supported} (HTTP/1.1 - RFC 2616) */
    132. int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
    133. /** {@code 507 Insufficient Storage} (WebDAV - RFC 2518) */
    134. int SC_INSUFFICIENT_STORAGE = 507;
    135. }

     ②、Spring框架的HttpStatus。

    1. package org.springframework.http;
    2. import org.springframework.lang.Nullable;
    3. /**
    4. * Enumeration of HTTP status codes.
    5. *
    6. *

      The HTTP status code series can be retrieved via {@link #series()}.

    7. *
    8. * @author Arjen Poutsma
    9. * @author Sebastien Deleuze
    10. * @author Brian Clozel
    11. * @since 3.0
    12. * @see HttpStatus.Series
    13. */
    14. public enum HttpStatus {
    15. // 1xx Informational
    16. /**
    17. * {@code 100 Continue}.
    18. */
    19. CONTINUE(100, Series.INFORMATIONAL, "Continue"),
    20. /**
    21. * {@code 101 Switching Protocols}.
    22. */
    23. SWITCHING_PROTOCOLS(101, Series.INFORMATIONAL, "Switching Protocols"),
    24. /**
    25. * {@code 102 Processing}.
    26. * @see WebDAV
    27. */
    28. PROCESSING(102, Series.INFORMATIONAL, "Processing"),
    29. /**
    30. * {@code 103 Checkpoint}.
    31. */
    32. CHECKPOINT(103, Series.INFORMATIONAL, "Checkpoint"),
    33. // 2xx Success
    34. /**
    35. * {@code 200 OK}.
    36. */
    37. OK(200, Series.SUCCESSFUL, "OK"),
    38. /**
    39. * {@code 201 Created}.
    40. */
    41. CREATED(201, Series.SUCCESSFUL, "Created"),
    42. /**
    43. * {@code 202 Accepted}.
    44. */
    45. ACCEPTED(202, Series.SUCCESSFUL, "Accepted"),
    46. /**
    47. * {@code 203 Non-Authoritative Information}.
    48. */
    49. NON_AUTHORITATIVE_INFORMATION(203, Series.SUCCESSFUL, "Non-Authoritative Information"),
    50. /**
    51. * {@code 204 No Content}.
    52. */
    53. NO_CONTENT(204, Series.SUCCESSFUL, "No Content"),
    54. /**
    55. * {@code 205 Reset Content}.
    56. */
    57. RESET_CONTENT(205, Series.SUCCESSFUL, "Reset Content"),
    58. /**
    59. * {@code 206 Partial Content}.
    60. */
    61. PARTIAL_CONTENT(206, Series.SUCCESSFUL, "Partial Content"),
    62. /**
    63. * {@code 207 Multi-Status}.
    64. * @see WebDAV
    65. */
    66. MULTI_STATUS(207, Series.SUCCESSFUL, "Multi-Status"),
    67. /**
    68. * {@code 208 Already Reported}.
    69. */
    70. ALREADY_REPORTED(208, Series.SUCCESSFUL, "Already Reported"),
    71. /**
    72. * {@code 226 IM Used}.
    73. */
    74. IM_USED(226, Series.SUCCESSFUL, "IM Used"),
    75. // 3xx Redirection
    76. /**
    77. * {@code 300 Multiple Choices}.
    78. */
    79. MULTIPLE_CHOICES(300, Series.REDIRECTION, "Multiple Choices"),
    80. /**
    81. * {@code 301 Moved Permanently}.
    82. */
    83. MOVED_PERMANENTLY(301, Series.REDIRECTION, "Moved Permanently"),
    84. /**
    85. * {@code 302 Found}.
    86. */
    87. FOUND(302, Series.REDIRECTION, "Found"),
    88. /**
    89. * {@code 302 Moved Temporarily}.
    90. * @deprecated in favor of {@link #FOUND} which will be returned from {@code HttpStatus.valueOf(302)}
    91. */
    92. @Deprecated
    93. MOVED_TEMPORARILY(302, Series.REDIRECTION, "Moved Temporarily"),
    94. /**
    95. * {@code 303 See Other}.
    96. */
    97. SEE_OTHER(303, Series.REDIRECTION, "See Other"),
    98. /**
    99. * {@code 304 Not Modified}.
    100. */
    101. NOT_MODIFIED(304, Series.REDIRECTION, "Not Modified"),
    102. /**
    103. * {@code 305 Use Proxy}.
    104. * @deprecated due to security concerns regarding in-band configuration of a proxy
    105. */
    106. @Deprecated
    107. USE_PROXY(305, Series.REDIRECTION, "Use Proxy"),
    108. /**
    109. * {@code 307 Temporary Redirect}.
    110. */
    111. TEMPORARY_REDIRECT(307, Series.REDIRECTION, "Temporary Redirect"),
    112. /**
    113. * {@code 308 Permanent Redirect}.
    114. * @see RFC 7238
    115. */
    116. PERMANENT_REDIRECT(308, Series.REDIRECTION, "Permanent Redirect"),
    117. // --- 4xx Client Error ---
    118. /**
    119. * {@code 400 Bad Request}.
    120. */
    121. BAD_REQUEST(400, Series.CLIENT_ERROR, "Bad Request"),
    122. /**
    123. * {@code 401 Unauthorized}.
    124. */
    125. UNAUTHORIZED(401, Series.CLIENT_ERROR, "Unauthorized"),
    126. /**
    127. * {@code 402 Payment Required}.
    128. */
    129. PAYMENT_REQUIRED(402, Series.CLIENT_ERROR, "Payment Required"),
    130. /**
    131. * {@code 403 Forbidden}.
    132. */
    133. FORBIDDEN(403, Series.CLIENT_ERROR, "Forbidden"),
    134. /**
    135. * {@code 404 Not Found}.
    136. */
    137. NOT_FOUND(404, Series.CLIENT_ERROR, "Not Found"),
    138. /**
    139. * {@code 405 Method Not Allowed}.
    140. */
    141. METHOD_NOT_ALLOWED(405, Series.CLIENT_ERROR, "Method Not Allowed"),
    142. /**
    143. * {@code 406 Not Acceptable}.
    144. */
    145. NOT_ACCEPTABLE(406, Series.CLIENT_ERROR, "Not Acceptable"),
    146. /**
    147. * {@code 407 Proxy Authentication Required}.
    148. */
    149. PROXY_AUTHENTICATION_REQUIRED(407, Series.CLIENT_ERROR, "Proxy Authentication Required"),
    150. /**
    151. * {@code 408 Request Timeout}.
    152. */
    153. REQUEST_TIMEOUT(408, Series.CLIENT_ERROR, "Request Timeout"),
    154. /**
    155. * {@code 409 Conflict}.
    156. */
    157. CONFLICT(409, Series.CLIENT_ERROR, "Conflict"),
    158. /**
    159. * {@code 410 Gone}.
    160. * @see
    161. */
    162. GONE(410, Series.CLIENT_ERROR, "Gone"),
    163. /**
    164. * {@code 411 Length Required}.
    165. * @see
    166. */
    167. LENGTH_REQUIRED(411, Series.CLIENT_ERROR, "Length Required"),
    168. /**
    169. * {@code 412 Precondition failed}.
    170. * @see
    171. */
    172. PRECONDITION_FAILED(412, Series.CLIENT_ERROR, "Precondition Failed"),
    173. /**
    174. * {@code 413 Payload Too Large}.
    175. * @since 4.1
    176. * @see
    177. */
    178. PAYLOAD_TOO_LARGE(413, Series.CLIENT_ERROR, "Payload Too Large"),
    179. /**
    180. * {@code 413 Request Entity Too Large}.
    181. * @deprecated in favor of {@link #PAYLOAD_TOO_LARGE} which will be
    182. * returned from {@code HttpStatus.valueOf(413)}
    183. */
    184. @Deprecated
    185. REQUEST_ENTITY_TOO_LARGE(413, Series.CLIENT_ERROR, "Request Entity Too Large"),
    186. /**
    187. * {@code 414 URI Too Long}.
    188. * @since 4.1
    189. * @see
    190. */
    191. URI_TOO_LONG(414, Series.CLIENT_ERROR, "URI Too Long"),
    192. /**
    193. * {@code 414 Request-URI Too Long}.
    194. * @deprecated in favor of {@link #URI_TOO_LONG} which will be returned from {@code HttpStatus.valueOf(414)}
    195. */
    196. @Deprecated
    197. REQUEST_URI_TOO_LONG(414, Series.CLIENT_ERROR, "Request-URI Too Long"),
    198. /**
    199. * {@code 415 Unsupported Media Type}.
    200. * @see
    201. */
    202. UNSUPPORTED_MEDIA_TYPE(415, Series.CLIENT_ERROR, "Unsupported Media Type"),
    203. /**
    204. * {@code 416 Requested Range Not Satisfiable}.
    205. */
    206. REQUESTED_RANGE_NOT_SATISFIABLE(416, Series.CLIENT_ERROR, "Requested range not satisfiable"),
    207. /**
    208. * {@code 417 Expectation Failed}.
    209. * @see
    210. */
    211. EXPECTATION_FAILED(417, Series.CLIENT_ERROR, "Expectation Failed"),
    212. /**
    213. * {@code 418 I'm a teapot}.
    214. * @see HTCPCP/1.0
    215. */
    216. I_AM_A_TEAPOT(418, Series.CLIENT_ERROR, "I'm a teapot"),
    217. /**
    218. * @deprecated See
    219. *
    220. */
    221. @Deprecated
    222. INSUFFICIENT_SPACE_ON_RESOURCE(419, Series.CLIENT_ERROR, "Insufficient Space On Resource"),
    223. /**
    224. * @deprecated See
    225. *
    226. */
    227. @Deprecated
    228. METHOD_FAILURE(420, Series.CLIENT_ERROR, "Method Failure"),
    229. /**
    230. * @deprecated
    231. * See
    232. */
    233. @Deprecated
    234. DESTINATION_LOCKED(421, Series.CLIENT_ERROR, "Destination Locked"),
    235. /**
    236. * {@code 422 Unprocessable Entity}.
    237. * @see WebDAV
    238. */
    239. UNPROCESSABLE_ENTITY(422, Series.CLIENT_ERROR, "Unprocessable Entity"),
    240. /**
    241. * {@code 423 Locked}.
    242. * @see WebDAV
    243. */
    244. LOCKED(423, Series.CLIENT_ERROR, "Locked"),
    245. /**
    246. * {@code 424 Failed Dependency}.
    247. * @see WebDAV
    248. */
    249. FAILED_DEPENDENCY(424, Series.CLIENT_ERROR, "Failed Dependency"),
    250. /**
    251. * {@code 425 Too Early}.
    252. * @since 5.2
    253. * @see RFC 8470
    254. */
    255. TOO_EARLY(425, Series.CLIENT_ERROR, "Too Early"),
    256. /**
    257. * {@code 426 Upgrade Required}.
    258. */
    259. UPGRADE_REQUIRED(426, Series.CLIENT_ERROR, "Upgrade Required"),
    260. /**
    261. * {@code 428 Precondition Required}.
    262. */
    263. PRECONDITION_REQUIRED(428, Series.CLIENT_ERROR, "Precondition Required"),
    264. /**
    265. * {@code 429 Too Many Requests}.
    266. */
    267. TOO_MANY_REQUESTS(429, Series.CLIENT_ERROR, "Too Many Requests"),
    268. /**
    269. * {@code 431 Request Header Fields Too Large}.
    270. */
    271. REQUEST_HEADER_FIELDS_TOO_LARGE(431, Series.CLIENT_ERROR, "Request Header Fields Too Large"),
    272. /**
    273. * {@code 451 Unavailable For Legal Reasons}.
    274. * @see
    275. * @since 4.3
    276. */
    277. UNAVAILABLE_FOR_LEGAL_REASONS(451, Series.CLIENT_ERROR, "Unavailable For Legal Reasons"),
    278. // --- 5xx Server Error ---
    279. /**
    280. * {@code 500 Internal Server Error}.
    281. */
    282. INTERNAL_SERVER_ERROR(500, Series.SERVER_ERROR, "Internal Server Error"),
    283. /**
    284. * {@code 501 Not Implemented}.
    285. */
    286. NOT_IMPLEMENTED(501, Series.SERVER_ERROR, "Not Implemented"),
    287. /**
    288. * {@code 502 Bad Gateway}.
    289. */
    290. BAD_GATEWAY(502, Series.SERVER_ERROR, "Bad Gateway"),
    291. /**
    292. * {@code 503 Service Unavailable}.
    293. */
    294. SERVICE_UNAVAILABLE(503, Series.SERVER_ERROR, "Service Unavailable"),
    295. /**
    296. * {@code 504 Gateway Timeout}.
    297. */
    298. GATEWAY_TIMEOUT(504, Series.SERVER_ERROR, "Gateway Timeout"),
    299. /**
    300. * {@code 505 HTTP Version Not Supported}.
    301. */
    302. HTTP_VERSION_NOT_SUPPORTED(505, Series.SERVER_ERROR, "HTTP Version not supported"),
    303. /**
    304. * {@code 506 Variant Also Negotiates}
    305. */
    306. VARIANT_ALSO_NEGOTIATES(506, Series.SERVER_ERROR, "Variant Also Negotiates"),
    307. /**
    308. * {@code 507 Insufficient Storage}
    309. * @see WebDAV
    310. */
    311. INSUFFICIENT_STORAGE(507, Series.SERVER_ERROR, "Insufficient Storage"),
    312. /**
    313. * {@code 508 Loop Detected}
    314. */
    315. LOOP_DETECTED(508, Series.SERVER_ERROR, "Loop Detected"),
    316. /**
    317. * {@code 509 Bandwidth Limit Exceeded}
    318. */
    319. BANDWIDTH_LIMIT_EXCEEDED(509, Series.SERVER_ERROR, "Bandwidth Limit Exceeded"),
    320. /**
    321. * {@code 510 Not Extended}
    322. */
    323. NOT_EXTENDED(510, Series.SERVER_ERROR, "Not Extended"),
    324. /**
    325. * {@code 511 Network Authentication Required}.
    326. */
    327. NETWORK_AUTHENTICATION_REQUIRED(511, Series.SERVER_ERROR, "Network Authentication Required");
    328. private static final HttpStatus[] VALUES;
    329. static {
    330. VALUES = values();
    331. }
    332. private final int value;
    333. private final Series series;
    334. private final String reasonPhrase;
    335. HttpStatus(int value, Series series, String reasonPhrase) {
    336. this.value = value;
    337. this.series = series;
    338. this.reasonPhrase = reasonPhrase;
    339. }
    340. /**
    341. * Return the integer value of this status code.
    342. */
    343. public int value() {
    344. return this.value;
    345. }
    346. /**
    347. * Return the HTTP status series of this status code.
    348. * @see HttpStatus.Series
    349. */
    350. public Series series() {
    351. return this.series;
    352. }
    353. /**
    354. * Return the reason phrase of this status code.
    355. */
    356. public String getReasonPhrase() {
    357. return this.reasonPhrase;
    358. }
    359. /**
    360. * Whether this status code is in the HTTP series
    361. * {@link org.springframework.http.HttpStatus.Series#INFORMATIONAL}.
    362. *

      This is a shortcut for checking the value of {@link #series()}.

    363. * @since 4.0
    364. * @see #series()
    365. */
    366. public boolean is1xxInformational() {
    367. return (series() == Series.INFORMATIONAL);
    368. }
    369. /**
    370. * Whether this status code is in the HTTP series
    371. * {@link org.springframework.http.HttpStatus.Series#SUCCESSFUL}.
    372. *

      This is a shortcut for checking the value of {@link #series()}.

    373. * @since 4.0
    374. * @see #series()
    375. */
    376. public boolean is2xxSuccessful() {
    377. return (series() == Series.SUCCESSFUL);
    378. }
    379. /**
    380. * Whether this status code is in the HTTP series
    381. * {@link org.springframework.http.HttpStatus.Series#REDIRECTION}.
    382. *

      This is a shortcut for checking the value of {@link #series()}.

    383. * @since 4.0
    384. * @see #series()
    385. */
    386. public boolean is3xxRedirection() {
    387. return (series() == Series.REDIRECTION);
    388. }
    389. /**
    390. * Whether this status code is in the HTTP series
    391. * {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR}.
    392. *

      This is a shortcut for checking the value of {@link #series()}.

    393. * @since 4.0
    394. * @see #series()
    395. */
    396. public boolean is4xxClientError() {
    397. return (series() == Series.CLIENT_ERROR);
    398. }
    399. /**
    400. * Whether this status code is in the HTTP series
    401. * {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}.
    402. *

      This is a shortcut for checking the value of {@link #series()}.

    403. * @since 4.0
    404. * @see #series()
    405. */
    406. public boolean is5xxServerError() {
    407. return (series() == Series.SERVER_ERROR);
    408. }
    409. /**
    410. * Whether this status code is in the HTTP series
    411. * {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or
    412. * {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}.
    413. *

      This is a shortcut for checking the value of {@link #series()}.

    414. * @since 5.0
    415. * @see #is4xxClientError()
    416. * @see #is5xxServerError()
    417. */
    418. public boolean isError() {
    419. return (is4xxClientError() || is5xxServerError());
    420. }
    421. /**
    422. * Return a string representation of this status code.
    423. */
    424. @Override
    425. public String toString() {
    426. return this.value + " " + name();
    427. }
    428. /**
    429. * Return the {@code HttpStatus} enum constant with the specified numeric value.
    430. * @param statusCode the numeric value of the enum to be returned
    431. * @return the enum constant with the specified numeric value
    432. * @throws IllegalArgumentException if this enum has no constant for the specified numeric value
    433. */
    434. public static HttpStatus valueOf(int statusCode) {
    435. HttpStatus status = resolve(statusCode);
    436. if (status == null) {
    437. throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
    438. }
    439. return status;
    440. }
    441. /**
    442. * Resolve the given status code to an {@code HttpStatus}, if possible.
    443. * @param statusCode the HTTP status code (potentially non-standard)
    444. * @return the corresponding {@code HttpStatus}, or {@code null} if not found
    445. * @since 5.0
    446. */
    447. @Nullable
    448. public static HttpStatus resolve(int statusCode) {
    449. // Use cached VALUES instead of values() to prevent array allocation.
    450. for (HttpStatus status : VALUES) {
    451. if (status.value == statusCode) {
    452. return status;
    453. }
    454. }
    455. return null;
    456. }
    457. /**
    458. * Enumeration of HTTP status series.
    459. *

      Retrievable via {@link HttpStatus#series()}.

    460. */
    461. public enum Series {
    462. INFORMATIONAL(1),
    463. SUCCESSFUL(2),
    464. REDIRECTION(3),
    465. CLIENT_ERROR(4),
    466. SERVER_ERROR(5);
    467. private final int value;
    468. Series(int value) {
    469. this.value = value;
    470. }
    471. /**
    472. * Return the integer value of this status series. Ranges from 1 to 5.
    473. */
    474. public int value() {
    475. return this.value;
    476. }
    477. /**
    478. * Return the {@code Series} enum constant for the supplied {@code HttpStatus}.
    479. * @param status a standard HTTP status enum constant
    480. * @return the {@code Series} enum constant for the supplied {@code HttpStatus}
    481. * @deprecated as of 5.3, in favor of invoking {@link HttpStatus#series()} directly
    482. */
    483. @Deprecated
    484. public static Series valueOf(HttpStatus status) {
    485. return status.series;
    486. }
    487. /**
    488. * Return the {@code Series} enum constant for the supplied status code.
    489. * @param statusCode the HTTP status code (potentially non-standard)
    490. * @return the {@code Series} enum constant for the supplied status code
    491. * @throws IllegalArgumentException if this enum has no corresponding constant
    492. */
    493. public static Series valueOf(int statusCode) {
    494. Series series = resolve(statusCode);
    495. if (series == null) {
    496. throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
    497. }
    498. return series;
    499. }
    500. /**
    501. * Resolve the given status code to an {@code HttpStatus.Series}, if possible.
    502. * @param statusCode the HTTP status code (potentially non-standard)
    503. * @return the corresponding {@code Series}, or {@code null} if not found
    504. * @since 5.1.3
    505. */
    506. @Nullable
    507. public static Series resolve(int statusCode) {
    508. int seriesCode = statusCode / 100;
    509. for (Series series : values()) {
    510. if (series.value == seriesCode) {
    511. return series;
    512. }
    513. }
    514. return null;
    515. }
    516. }
    517. }

    HttpMethod

    1. package org.springframework.http;
    2. import java.util.HashMap;
    3. import java.util.Map;
    4. import org.springframework.lang.Nullable;
    5. /**
    6. * Enumeration of HTTP request methods. Intended for use
    7. * with {@link org.springframework.http.client.ClientHttpRequest}
    8. * and {@link org.springframework.web.client.RestTemplate}.
    9. *
    10. * @author Arjen Poutsma
    11. * @author Juergen Hoeller
    12. * @since 3.0
    13. */
    14. public enum HttpMethod {
    15. GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
    16. private static final Map mappings = new HashMap<>(16);
    17. static {
    18. for (HttpMethod httpMethod : values()) {
    19. mappings.put(httpMethod.name(), httpMethod);
    20. }
    21. }
    22. /**
    23. * Resolve the given method value to an {@code HttpMethod}.
    24. * @param method the method value as a String
    25. * @return the corresponding {@code HttpMethod}, or {@code null} if not found
    26. * @since 4.2.4
    27. */
    28. @Nullable
    29. public static HttpMethod resolve(@Nullable String method) {
    30. return (method != null ? mappings.get(method) : null);
    31. }
    32. /**
    33. * Determine whether this {@code HttpMethod} matches the given method value.
    34. * @param method the HTTP method as a String
    35. * @return {@code true} if it matches, {@code false} otherwise
    36. * @since 4.2.4
    37. */
    38. public boolean matches(String method) {
    39. return name().equals(method);
    40. }
    41. }
  • 相关阅读:
    Shell及Linux三剑客grep、sed、awk
    jQuery学习:属性
    Reflection - 浅谈Python反射
    F28069的cpu定时器
    CMake入门教程【核心篇】设置和使用缓存变量
    Go坑:time.After可能导致的内存泄露问题分析
    Elasticsearch查询
    BBR/CUBIC 共存时的 buffer 挤兑
    什么是数据中心的测试负载?
    ubuntu 18.04 OAK-D系列相机运行VINS-Fusion 双目+IMU
  • 原文地址:https://blog.csdn.net/HcJsJqJSSM/article/details/126797480