我们项目都是配置一个 RestTemplate bean ,然后所有外部请求都用它,现在有个需求的超时时间要求不一样,就得重新定义一个 bean ,又得怼一堆配置,麻烦,直接用 simpleClientHttpRequestFactory 又不能用到连接池,所以为何 RestTemplate 不支持对每个请求定制化,就像事务超时设置 @Transactional(timeout = 3),每个都可以不一样,唯独这个外部请求没有这种功能,就感觉不太合理。
问了 AI ,可以用下面的方法,但感觉还是太麻烦了,不够简单优雅
步骤 1:创建一个全局共享的、带连接池的 CloseableHttpClient
public class PooledRestClient { private static final CloseableHttpClient httpClient; static { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(100); cm.setDefaultMaxPerRoute(20); // 可选:设置空闲连接清理 httpClient = HttpClients.custom() .setConnectionManager(cm) .evictIdleConnections(60, TimeUnit.SECONDS) .build(); } // 核心方法:动态发起请求 public static ResponseEntity<String> exchange( String url, HttpMethod method, HttpEntity<?> requestEntity, Class<String> responseType, int connectTimeoutMs, int readTimeoutMs) { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory( httpClient); factory.setConnectTimeout(connectTimeoutMs); factory.setReadTimeout(readTimeoutMs); RestTemplate restTemplate = new RestTemplate(factory); return restTemplate.exchange(url, method, requestEntity, responseType); }}步骤 2:在业务代码中直接调用(无需 Spring Bean )
// 动态构造请求头HttpHeaders headers = new HttpHeaders();headers.set("Authorization", "Bearer " + token);headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<String> entity = new HttpEntity<>("{\"key\":\"value\"}", headers);// 发起带连接池的请求(每次 URL/Token/Body 都可不同)ResponseEntity<String> response = PooledRestClient.exchange( "https://api.example.com/v1/data", HttpMethod.POST, entity, String.class, 3000, // connect timeout 10000 // read timeout);
