web-dev-qa-db-ja.com

スプリングブート-レストテンプレートとレストテンプレートビルダー

私が知っているように、RestTemplateBuilderRestTemplateの一種のファクトリーです。私はそれを使用することについていくつかの質問があります:

  1. 多くの場合、例では@Configurationクラスに次のようなものがあります。

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

    @ServiceクラスごとにRestTemplateをインスタンス化すべきではありませんか?もしそうなら、それをカスタマイズする方法は?

  2. Springのリファレンスでは、RestTemplateBuilderRestTemplateCustomizerを介してカスタマイズする必要があります。 1つのビルダーで多数のIPアドレスから多数のURIを管理する方法

  3. BasicAuthenticationを介してすべてのRestTemplatesRestTemplateBuilder globalyを追加するにはどうすればよいですか?

手伝ってくれてありがとう。

[〜#〜] update [〜#〜]

私のアプリケーションは、異なるIPとURLの多くのサーバーからRESTサービスを呼び出します。したがって、論理的には、RestTemplatesが多数ある状況です。

サーバーごとにファクトリー(RestTemplateBuilder)を作成しようとしています-サーバーA、B、Cとしましょう。基本認証を追加する方法を知っています。しかし、たとえば、サーバーAではなくサーバーBでは基本認証が必要な場合はどうでしょうか。

サーバーごとにRestTemplateBuilderを1つ持つことを考えています。これを手動で行いたくありません-Springメカニズムを使用したいと思います。

何か助け?

8
javovy
  1. いいえ、必要はありません。通常、残りのテンプレートインスタンスを使用します。異なるURLを渡し、毎回それに応じてパラメーターを要求します。

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

RestTemplateCustomizer Beanは、自動構成のRestTemplateBuilderに自動的に追加されます。さらに、additionalCustomizers(RestTemplateCustomizer…)を呼び出すことで、追加のカスタマイザーを含む新しいRestTemplateBuilderを作成できます。

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

次のように構成をセットアップしました。

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

したがって、RestTempleを直接使用するのではなく、認証システムを使用します。この種の標準的なパターンは見つかりませんでしたが、これはうまくいくようです。

2