为何 RestTemplate 无法定制请求

50 天前
 cocong

我们项目都是配置一个 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
);
3185 次点击
所在节点    Java
8 条回复
xtreme1
50 天前
用 WebClient, 可以拿到一个 CompletableFuture
potatowish
50 天前
spring 5.0 webclient 就可以吧,每个请求可以单独设置超时时间
momo31
50 天前
直接用 okhttp 呢
tedzhou1221
50 天前
我们之前的项目改用 Forest http
doppler
50 天前
用 webclient 加 timeout 操作符
nananqujava
50 天前
Forest 好用 https://forest.kim/
Need4more
50 天前
你这太罗嗦了,用 RestTemplateBuilder

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(5))
.build();
}
looo
50 天前
@Need4more 我之前项目也是这么搞,一个三方一个 bean ,每一家的接口超时不一样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1171142

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX