jgg521ccm最新版本更新:开启智能生活新纪元

核心内容摘要

44444444444免费观看电视大全在线:点亮您的娱乐世界
吃瓜网:围观世界的万象,品味人生的百味

小舞献祭:爱之极致,绝美牺牲

视频看了几百小时还迷糊关注我几分钟让你秒懂

为什么需要封装 HTTP 工具类在实际开发中我们经常要调用第三方接口比如支付宝/微信支付回调短信平台发送验证码对接 ERP、CRM 系统调用 AI 大模型 API。

如果每次都写HttpURLConnection或RestTemplate的样板代码不仅重复、难维护还容易出错超时、重试、日志、异常处理等。

✅封装目标统一超时控制自动重试机制请求/响应日志记录异常统一处理支持 JSON、Form 表单等多种格式易于单元测试。

使用 Spring Boot 推荐方案RestTemplate 封装 虽然 Spring 6 推出了WebClient响应式但大多数项目仍用RestTemplate本文以它为基础。

添加依赖Spring Boot 默认已包含dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency

创建 HTTP 工具类核心import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; Component public class HttpUtil { private static final Logger log LoggerFactory.getLogger(HttpUtil.class); private final RestTemplate restTemplate; private final ObjectMapper objectMapper; // 注入 Spring 管理的 RestTemplate 和 ObjectMapper public HttpUtil(RestTemplate restTemplate, ObjectMapper objectMapper) { this.restTemplate restTemplate; this.objectMapper objectMapper; } /** * POST JSON 请求 */ public T T postJson(String url, Object requestBody, ClassT responseType) { return doRequest(url, HttpMethod.POST, buildJsonEntity(requestBody), responseType); } /** * GET 请求带 Query 参数 */ public T T get(String url, MapString, Object params, ClassT responseType) { String urlWithParams appendQueryParams(url, params); return doRequest(urlWithParams, HttpMethod.GET, null, responseType); } /** * POST Form 表单 */ public T T postForm(String url, MapString, String formData, ClassT responseType) { HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMapString, String map new LinkedMultiValueMap(); map.setAll(formData); HttpEntityMultiValueMapString, String entity new HttpEntity(map, headers); return doRequest(url, HttpMethod.POST, entity, responseType); } // ------------------ 内部方法 ------------------ private T HttpEntityT buildJsonEntity(T body) { HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); return new HttpEntity(body, headers); } private String appendQueryParams(String url, MapString, Object params) { if (params null || params.isEmpty()) return url; StringBuilder sb new StringBuilder(url); if (!url.contains(?)) sb.append(?); else if (!url.endsWith()) sb.append(); params.forEach((k, v) - sb.append(k).append().append(v).append()); return sb.substring(0, sb.length() -

; // 去掉最后一个 } private T T doRequest(String url, HttpMethod method, HttpEntity? entity, ClassT responseType) { long start System.currentTimeMillis(); try { // 记录请求日志 log.info( HTTP {} Request: {}, method, url); if (entity ! null entity.getBody() ! null) { String bodyStr objectMapper.writeValueAsString(entity.getBody()); log.info( Request Body: {}, bodyStr); } ResponseEntityT response restTemplate.exchange(url, method, entity, responseType); // 记录响应日志 long cost System.currentTimeMillis() - start; log.info( HTTP Response Status: {}, Cost: {}ms, response.getStatusCode(), cost); if (response.getBody() ! null) { log.debug( Response Body: {}, response.getBody()); } return response.getBody(); } catch (ResourceAccessException e) { log.error(HTTP 请求超时或网络异常 | URL: {} | Error: {}, url, e.getMessage()); throw new RuntimeException(调用三方接口超时, e); } catch (RestClientException e) { log.error(HTTP 客户端错误 | URL: {} | Error: {}, url, e.getMessage()); throw new RuntimeException(调用三方接口失败, e); } catch (Exception e) { log.error(HTTP 请求未知异常 | URL: {} | Error: {}, url, e.getMessage(), e); throw new RuntimeException(调用三方接口异常, e); } } }⚙️

配置 RestTemplate带超时和重试

自定义 RestTemplate BeanConfiguration public class RestTemplateConfig { Bean public RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory factory new HttpComponentsClientHttpRequestFactory(); factory.setConnectTimeout(

; // 连接超时 5s factory.setReadTimeout(

; // 读取超时 10s factory.setConnectionRequestTimeout(

; // 从连接池获取连接超时 RestTemplate restTemplate new RestTemplate(factory); // 可选添加拦截器如统一 header return restTemplate; } } 需要额外依赖用于设置超时dependency groupIdorg.apache.httpcomponents/groupId artifactIdhttpclient/artifactId /dependency

使用示例场景 1调用支付回调接口POST JSONService public class PaymentService { Autowired private HttpUtil httpUtil; public void notifyPayment(String orderId) { MapString, Object request Map.of( orderId, orderId, status, SUCCESS ); // 调用三方 String result httpUtil.postJson(https://partner.com/api/notify, request, String.class); log.info(通知结果: {}, result); } }场景 2获取用户信息GET 带参数MapString, Object params Map.of(userId, 12345, token, abc); User user httpUtil.get(https://api.example.com/user, params, User.class);场景 3发送短信POST FormMapString, String form Map.of( mobile, 13800138000, content, 您的验证码是123456 ); String resp httpUtil.postForm(https://sms.provider.com/send, form, String.class);❌

反例 常见错误反例 1每次 new RestTemplate无法复用连接池// ❌ 错误每次创建新实例性能差无超时控制 RestTemplate rt new RestTemplate(); rt.postForObject(url, body, String.class);✅ 正确注入 Spring 管理的 Bean。

反例 2不处理异常直接吞掉try { restTemplate.getForObject(url, String.class); } catch (Exception e) { // 啥也不干 } 后果线上故障无法排查✅ 正确记录日志 抛出业务异常。

反例 3敏感信息打印到日志log.info(请求体: {}, body); // 包含密码、token✅ 建议生产环境debug级别才打 body敏感字段脱敏如password***。

⚠️

进阶建议生产级功能实现方式重试机制使用Spring Retry或Resilience4j熔断降级集成 Sentinel / HystrixMetrics 监控记录调用次数、耗时、成功率MicrometerMock 测试使用WireMock模拟三方接口HTTPS 双向认证配置 SSLContext金融场景

七、

总结封装后的HttpUtil具备✅ 统一入口调用简单✅ 自动日志请求/响应/耗时✅ 超时控制✅ 异常包装✅ 支持多种格式JSON/Form/GET✅ 易于扩展加签名、加 header 等。

从此告别“复制粘贴式” HTTP 调用视频看了几百小时还迷糊关注我几分钟让你秒懂

纯劳务不分等级资质-纯劳务不分等级资质应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123