web-dev-qa-db-fra.com

Spring Boot - Rest Template et Rest Template Builder

Comme je sais, le RestTemplateBuilder est une sorte d'usine pour RestTemplate. J'ai quelques questions sur son utilisation:

  1. Très souvent, dans les exemples, il y a quelque chose comme ça dans @Configuration classe:

    @Bean
    public RestTemplate getRestClient() {
        RestTemplate restClient = new RestTemplate();
        ...
        return restClient;
    }
    

    Ne doit pas RestTemplate être instancié par @Service classe? Si oui, comment le personnaliser?

  2. La référence du printemps indique que RestTemplateBuilder doit être personnalisé via RestTemplateCustomizer. Comment gérer plusieurs URI à partir de plusieurs adresses IP avec un seul constructeur?

  3. Comment ajouter globalement BasicAuthentication à tous les RestTemplates via RestTemplateBuilder, et est-ce une bonne pratique?

Merci pour l'aide.

MISE À JOUR :

Mon application appelle des services de repos à partir de nombreux serveurs sur différentes adresses IP et URL - c'est donc logiquement la situation où j'ai beaucoup de RestTemplates.

J'essaie d'avoir une usine (RestTemplateBuilder) par serveur - disons les serveurs A, B, C. Je sais comment ajouter une authentification de base. Mais que faire par exemple lorsque je veux une authentification de base pour le serveur A mais pas pour le serveur B?

Je pense à avoir un RestTemplateBuilder par serveur. Je ne veux pas le faire manuellement - je préférerais utiliser les mécanismes Spring.

De l'aide ?

8
javovy
  1. Non, vous n'en avez pas besoin, généralement vous aurez une instance de modèle de repos, et vous passerez une URL différente et demanderez des paramètres en conséquence à chaque fois.

    String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, vars);
    
    Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class);
    
  2. Un exemple descriptif de doc de printemps , vous pouvez ajouter autant de personnalisateurs au générateur

    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));
        }
    
    }
    

Tous les beans RestTemplateCustomizer seront automatiquement ajoutés au RestTemplateBuilder auto-configuré. De plus, un nouveau RestTemplateBuilder avec des personnalisateurs supplémentaires peut être créé en appelant additionalCustomizers (RestTemplateCustomizer…)

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

J'ai mis en place ma configuration comme ceci:

@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;
}

Chaque fois que Spring injecte un RestTemplateBuilder, il le configure à l'aide de ce RestTemplateCustomizer pour utiliser ClientHttpRequestFactory. Vous devrez peut-être effectuer différentes personnalisations, ou peut-être aucune, auquel cas ne déclarez pas le bean.

Pour ajouter l'en-tête d'authentification, vous devrez connaître le nom d'utilisateur et le mot de passe, que vous ne connaîtrez probablement pas avant l'exécution. J'ai donc créé un bean Authenticator:

@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
        }
    }
}

Cela me permet de gérer les échecs d'authentification de manière standard pour toutes les demandes, ce dont j'ai besoin dans mon application.

Il est injecté dans d'autres grains et utilisé comme ceci:

@Autowired
private Authenticator authenticator;

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

Vous utiliseriez donc l'Authenticator plutôt que d'utiliser le RestTemple directement. Je n'ai trouvé aucun modèle standard pour ce genre de chose, mais cela semble fonctionner.

2
whistling_marmot