Поиск…


Загрузка большого файла

getForObject и getForEntity для RestTemplate загружают весь ответ в памяти. Это не подходит для загрузки больших файлов, поскольку это может вызвать исключения из памяти. В этом примере показано, как передать ответ запроса GET.

RestTemplate restTemplate // = ...;

// Optional Accept header
RequestCallback requestCallback = request -> request.getHeaders()
        .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));

// Streams the response instead of loading it all in memory
ResponseExtractor<Void> responseExtractor = response -> {
    // Here I write the response to a file but do what you like
    Path path = Paths.get("some/path");
    Files.copy(response.getBody(), path);
    return null;
};
restTemplate.execute(URI.create("www.something.com"), HttpMethod.GET, requestCallback, responseExtractor);

Обратите внимание, что вы не можете просто вернуть InputStream из экстрактора, потому что к моменту возвращения метода выполнения базовое соединение и поток уже закрыты.

Использование превентивной базовой проверки подлинности с помощью RestTemplate и HttpClient

Упреждающая базовая аутентификация - это практика отправки HTTP-идентификаторов аутентификации (имя пользователя и пароль) до того, как сервер ответит с ответом 401 запрашивающим их. Это может сохранить запрос в оба конца при использовании REST apis, который, как известно, требует базовой аутентификации.

Как описано в документации Spring , Apache HttpClient может использоваться в качестве базовой реализации для создания HTTP-запросов с использованием HttpComponentsClientHttpRequestFactory . HttpClient может быть сконфигурирован так, чтобы выполнять предварительную базовую аутентификацию .

Следующий класс расширяет HttpComponentsClientHttpRequestFactory чтобы обеспечить предварительную базовую аутентификацию.

/**
 * {@link HttpComponentsClientHttpRequestFactory} with preemptive basic
 * authentication to avoid the unnecessary first 401 response asking for
 * credentials.
 * <p>
 * Only preemptively sends the given credentials to the given host and
 * optionally to its subdomains. Matching subdomains can be useful for APIs
 * using multiple subdomains which are not always known in advance.
 * <p>
 * Other configurations of the {@link HttpClient} are not modified (e.g. the
 * default credentials provider).
 */
public class PreAuthHttpComponentsClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {

    private String hostName;
    private boolean matchSubDomains;
    private Credentials credentials;

    /**
     * @param httpClient
     *            client
     * @param hostName
     *            host name
     * @param matchSubDomains
     *            whether to match the host's subdomains
     * @param userName
     *            basic authentication user name
     * @param password
     *            basic authentication password
     */
    public PreAuthHttpComponentsClientHttpRequestFactory(HttpClient httpClient, String hostName,
            boolean matchSubDomains, String userName, String password) {
        super(httpClient);
        this.hostName = hostName;
        this.matchSubDomains = matchSubDomains;
        credentials = new UsernamePasswordCredentials(userName, password);
    }

    @Override
    protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
        // Add AuthCache to the execution context
        HttpClientContext context = HttpClientContext.create();
        context.setCredentialsProvider(new PreAuthCredentialsProvider());
        context.setAuthCache(new PreAuthAuthCache());
        return context;
    }

    /**
     * @param host
     *            host name
     * @return whether the configured credentials should be used for the given
     *         host
     */
    protected boolean hostNameMatches(String host) {
        return host.equals(hostName) || (matchSubDomains && host.endsWith("." + hostName));
    }

    private class PreAuthCredentialsProvider extends BasicCredentialsProvider {
        @Override
        public Credentials getCredentials(AuthScope authscope) {
            if (hostNameMatches(authscope.getHost())) {
                // Simulate a basic authenticationcredentials entry in the
                // credentials provider.
                return credentials;
            }
            return super.getCredentials(authscope);
        }
    }

    private class PreAuthAuthCache extends BasicAuthCache {
        @Override
        public AuthScheme get(HttpHost host) {
            if (hostNameMatches(host.getHostName())) {
                // Simulate a cache entry for this host. This instructs
                // HttpClient to use basic authentication for this host.
                return new BasicScheme();
            }
            return super.get(host);
        }
    }
}

Это можно использовать следующим образом:

HttpClientBuilder builder = HttpClientBuilder.create();
ClientHttpRequestFactory requestFactory =
    new PreAuthHttpComponentsClientHttpRequestFactory(builder.build(),
        "api.some-host.com", true, "api", "my-key");
RestTemplate restTemplate = new RestTemplate(requestFactory);

Использование базовой проверки подлинности с HttpClient HttpComponent

Использование HttpClient в RestTemplate базовой реализации RestTemplate для создания HTTP-запросов позволяет автоматически обрабатывать базовые запросы аутентификации (ответ http 401) при взаимодействии с API-интерфейсами. В этом примере показано, как настроить RestTemplate для достижения этого.

// The credentials are stored here
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        // AuthScope can be configured more extensively to restrict
        // for which host/port/scheme/etc the credentials will be used.
        new AuthScope("somehost", AuthScope.ANY_PORT), 
        new UsernamePasswordCredentials("username", "password"));

// Use the credentials provider
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultCredentialsProvider(credsProvider);

// Configure the RestTemplate to use HttpComponent's HttpClient
ClientHttpRequestFactory requestFactory =
        new HttpComponentsClientHttpRequestFactory(builder.build());
RestTemplate restTemplate = new RestTemplate(requestFactory);

Настройка заголовков на запрос Spring RestTemplate

Способы exchange RestTemplate позволяют указать HttpEntity которые будут записаны в запрос при выполнении метода. Вы можете добавить заголовки (такой пользовательский агент, реферер ...) к этому объекту:

public void testHeader(final RestTemplate restTemplate){
        //Set the headers you need send
        final HttpHeaders headers = new HttpHeaders();
        headers.set("User-Agent", "eltabo");

        //Create a new HttpEntity
        final HttpEntity<String> entity = new HttpEntity<String>(headers);
        
        //Execute the method writing your HttpEntity to the request
        ResponseEntity<Map> response = restTemplate.exchange("https://httpbin.org/user-agent", HttpMethod.GET, entity, Map.class);        
        System.out.println(response.getBody());
    }

Также вы можете добавить перехватчик в свой RestTemplate если вам нужно добавить одни и те же заголовки к нескольким запросам:

public void testHeader2(final RestTemplate restTemplate){
    //Add a ClientHttpRequestInterceptor to the RestTemplate
    restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor(){
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            request.getHeaders().set("User-Agent", "eltabo");//Set the header for each request
            return execution.execute(request, body);
        }
    }); 
    
    ResponseEntity<Map> response = restTemplate.getForEntity("https://httpbin.org/user-agent", Map.class);        
    System.out.println(response.getBody());
    
    ResponseEntity<Map> response2 = restTemplate.getForEntity("https://httpbin.org/headers", Map.class);        
    System.out.println(response2.getBody());
}

Generics получается из Spring RestTemplate

Чтобы RestTemplate понимал общий возвращаемый контент, нам нужно определить ссылку на тип результата.

org.springframework.core.ParameterizedTypeReference введен с 3.2

Wrapper<Model> response = restClient.exchange(url, 
                          HttpMethod.GET, 
                          null, 
                          new ParameterizedTypeReference<Wrapper<Model>>() {}).getBody();

Может быть полезно получить, например, List<User> с контроллера.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow