春天启动 - 休息模板和休息模板生成器

时间:2016-10-10 11:46:48

标签: java spring rest spring-mvc

据我所知,RestTemplateBuilderRestTemplate的某种工厂。我有一些关于使用它的问题:

  1. @Configuration类:

    中,通常会有一些例子
    @Bean
    public RestTemplate getRestClient() {
        RestTemplate restClient = new RestTemplate();
        ...
        return restClient;
    }
    

    不应该RestTemplate每个@Service类实例化RestTemplateBuilder吗?如果是这样,如何定制它?

  2. Spring引用说RestTemplateCustomizer应该通过BasicAuthentication进行自定义。如何使用一个构建器从多个IP地址管理多个URI?

  3. 如何通过RestTemplates向所有RestTemplateBuilder添加RestTemplates全球,这是一个好习惯吗?

  4. 感谢您的帮助。

    更新

    我的应用程序调用来自不同IP和网址的许多服务器的休息服务 - 所以对我来说逻辑上就是我有很多RestTemplateBuilder的情况。

    我试图为每台服务器建立一个工厂(RestTemplateBuilder) - 让我们说服务器A,B,C。我知道如何添加基本身份验证。但是,例如,当我想要服务器A的基本身份验证而不是服务器B的基本身份验证时呢?

    我认为每台服务器有一个{ "_id": { "$oid": "5654a8f0d487dd1434571a6e" }, "ValidationDate": { "$date": "2015-11-24T13:06:19.363Z" }, "DataRaw": " WL 00100100012015-08-28 02:44:17+0000+ 16.81 8.879 1084.00", "ReadingsAreValid": true, "locationID": " WL 001", "Readings": { "pH": { "value": 8.879 }, "SensoreDate": { "value": { "$date": "2015-08-28T02:44:17.000Z" } }, "temperature": { "value": 16.81 }, "Conductivity": { "value": 1084 } }, "HMAC":"ecb98d73fcb34ce2c5bbcc9c1265c8ca939f639d791a1de0f6275e2d0d71a801" } 。我不想手动执行此操作 - 我更愿意使用Spring机制。

    任何帮助?

2 个答案:

答案 0 :(得分:6)

  1. 不,您不需要,通常您将拥有休息模板实例,并且您将传递不同的网址,并且每次都会相应地请求参数。

    String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, vars);
    
    Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class);
    
  2. 来自spring doc的描述性示例,您可以向构建器添加任意数量的自定义程序

    public class ProxyCustomizer implements RestTemplateCustomizer {
    
        @Override
        public void customize(RestTemplate restTemplate) {
            HttpHost proxy = new HttpHost("proxy.example.com");
            HttpClient httpClient = HttpClientBuilder.create()
                    .setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
    
                        @Override
                        public HttpHost determineProxy(HttpHost target,
                                HttpRequest request, HttpContext context)
                                        throws HttpException {
                            if (target.getHostName().equals("192.168.0.5")) {
                                return null;
                            }
                            return super.determineProxy(target, request, context);
                        }
    
                    }).build();
            restTemplate.setRequestFactory(
                    new HttpComponentsClientHttpRequestFactory(httpClient));
        }
    
    }
    
  3.   

    任何RestTemplateCustomizer bean都会自动添加到   自动配置的RestTemplateBuilder。此外,一个新的   可以创建具有其他自定义程序的RestTemplateBuilder   调用additionalCustomizers(RestTemplateCustomizer ...)

    @Bean
    public RestTemplateBuilder restTemplateBuilder() {
       return new RestTemplateBuilder()
            .rootUri(rootUri)
            .basicAuthorization(username, password);
    }
    

答案 1 :(得分:2)

我已经设置了这样的配置:

@Bean
public RestTemplateCustomizer restTemplateCustomizer() {
    return restTemplate -> {
        restTemplate.setRequestFactory(clientHttpRequestFactory());
    };
}

@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
    SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(connectionTimeoutMs);
    clientHttpRequestFactory.setReadTimeout(connectionTimeoutMs);
    clientHttpRequestFactory.setBufferRequestBody(false);
    return clientHttpRequestFactory;
}

每当Spring注入RestTemplateBuilder时,它将使用此RestTemplateCustomizer配置它以使用ClientHttpRequestFactory。您可能需要进行一些不同的自定义,或者在这种情况下不需要声明bean。

要添加身份验证标头,您需要知道用户名和密码,在运行时可能无法知道。所以我创建了一个Authenticator bean:

@Component
public class Authenticator {

    @Autowired
    private RestTemplateBuilder restTemplateBuilder;

    public void withAuthenticationHeader(String username, String password, Consumer<RestTemplate> doAuthenticated) {
        RestTemplate restTemplate =
            restTemplateBuilder
                .basicAuthorization(username, password)
                .build();

        try {
            doAuthenticated.accept(restTemplate);

        } catch (HttpClientErrorException exception) {
            // handle the exception
        }
    }
}

这使我能够以标准方式处理所有请求的身份验证失败,这正是我在我的应用程序中所需要的。

它被注入其他bean并像这样使用:

@Autowired
private Authenticator authenticator;

public void transmit() {
    authenticator.withAuthenticationHeader(username, password, restTemplate -> 
        restTemplate.postForLocation(url, request));
}

所以你要使用Authenticator而不是直接使用RestTemple。 我找不到任何这种标准的模式,但这似乎有效。