繁体   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