spring
RestTemplate
Поиск…
Загрузка большого файла
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>
с контроллера.