簡體   English   中英

如何為 Spring 中的每個客戶端配置和構建自定義 RestTemplate?

[英]How to configure and build a custom RestTemplate for each client in Spring?

我正在使用 Spring RestTemplate 執行來自我的應用程序的 HTTP 請求。 我們需要調用幾個服務,一些在 Internet 上,一些在 Intranet 上,一些快速而一些慢。 我被指示為每個服務配置自定義設置,基本上是連接超時、讀取超時。

這些設置將非常具體,例如,托管在 Intranet 上的服務將有約 2-5 秒的超時,而它們為 99.9% 的請求提供 1000 毫秒的 SLA。 而其他第三方服務大約 10-60 秒。

由於只能在工廠中為模板設置這些參數,因此我正在創建許多具有不同工廠的 bean,它們僅在超時方面有所不同。 像這樣的東西:

@Bean
RestTemplate restTemplate() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
    factory.setReadTimeout(20000);
    factory.setConnectTimeout(5000);
    RestTemplate restTemplate = new RestTemplate(factory);
}

恐怕這最終會造成維護噩夢。 能否以更好的方式解決?

PS:該應用程序是一個調用各種服務的單體。

您將不得不創建多個 RestTemplates 並分配超時、連接池大小。 連接池將大大提高性能

我已經對連接屬性進行了硬編碼,您可以從 application.properties 文件中選擇它

@Configuration
class RestTemplateConfigs {
    @Bean
    public HttpClient httpClient() {
        return HttpClientBuilder.create()
                .setMaxConnPerRoute(200)
                .setMaxConnTotal(50)
                .setConnectionTimeToLive(10L, TimeUnit.SECONDS)
                .build();
    }

    @Bean(name = "restTemplate1")
    RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
        RestTemplate restTemplate = new RestTemplate(factory);
        return restTemplate;
    }
}

您可以創建多個 RestTemplates 並使用限定符名稱對其進行自動裝配。

免責聲明:我的回答建議使用另一個 Http 客戶端而不是 Rest 模板 - 如果您必須使用 Rest 模板,我的回答將是無關緊要的。

我處理了一個類似的設計問題,這就是我所做的。 我編寫了自己的 HttpClient class。 它使用起來比大多數已知的 Http 客戶端簡單得多。 This class could be used on its own or (and this is relevant for your case) it could be used as a parent class for a group of classes (implementing the same interface) where each class will be an Http client for specific Rest Service. 在此 class 上,您可以預先設置目標 URL 和所有參數(例如讀取和連接超時等)。 預設此 class 后,您需要做的就是調用 sendHttpRequestMethod()。 Just to expand a bit - lets say you have a User Rest service with CRUD API implemented by particular URL calls with different HTTP methods and may be different URLs. (比如說除了創建(POST)更新(PUT)讀取(GET)和刪除(DELETE)方法之外,這些方法位於 HTTP://www.myserver.com:8083/user 說您還將有方法激活和停用( say both GET) at URLs HTTP://www.myserver.com:8083/user/activate/ and HTTP://www.myserver.com:8083/user/deactivate. So, in this case, your Http client will set all required timeouts and other configurations and it will also have pre-set target URL HTTP://www.myserver.com:8083/user. and it will have six methods as mentioned above, where each one will simply invoke the parent class method sendHttpRequest()。當然,對於激活和停用方法,您將需要到 append “激活”和“停用”預設基礎 URL 的后綴。 因此,對於每個 REST 服務,您可以輕松地創建一個專用的 Http 客戶端,因為基礎 class 已經完成了大部分工作。 除此之外,我還為任何一組實現相同接口的類編寫了一個自填充工廠。 使用該工廠,您所要做的就是編寫額外的 Http 客戶端,工廠將檢測到它,並將通過預定義的名稱或 class 的名稱(根據您的選擇)自行提供。 這一切對我來說都很好,我將它打包到名為 MgntUtils 的開源庫中,並在MavenGithub上發布(帶有源代碼和 Javadoc。JavaDoc 可在此處獲得)。 有關自填充工廠的詳細說明,請參見此處的 Javadoc。 此外,關於庫的一般文章可以在這里找到,關於自填充工廠的想法和實現的具體文章可以在這里找到。 源代碼中的 Package com.mgnt.lifecycle.management.example 包含一個工作示例。 我希望這有幫助。

使用 RestTemplate bean 的參數化構造解決了我的問題。 bean 現在配置為:

    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public RestTemplate getRestTemplate(String configParam){
        int connectionTimeout; //get from config using configParam
        int readTimeout;  //get from config using configParam
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(connectionTimeout);
        factory.setReadTimeout(readTimeout);

        return new RestTemplate(factory);
    }

除了@Autowiring 這個字段,它可以被注入可能是@PostConstruct 方法,如下圖所示。 依賴 bean 可以執行以下操作:

@Autowire
BeanFactory beanFactory;

RestTemplate restTemplate;

@PostConstruct
public void init(){
    restTemplate = beanFactory.getBean(RestTemplate.class, configParam);
}

在這里,您可以將帶有自定義設置的 bean 注入到restTemplate中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM