Szukaj…


Pobieranie dużego pliku

Metody getForObject i getForEntity RestTemplate ładują całą odpowiedź do pamięci. Nie nadaje się do pobierania dużych plików, ponieważ może powodować wyjątki braku pamięci. Ten przykład pokazuje, jak przesyłać strumieniowo odpowiedź na żądanie 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);

Zauważ, że nie możesz po prostu zwrócić InputStream z ekstraktora, ponieważ do czasu powrotu metody wykonania, podstawowe połączenie i strumień są już zamknięte.

Korzystanie z zapobiegawczego podstawowego uwierzytelniania z RestTemplate i HttpClient

Podstawowe uwierzytelnianie zapobiegawcze polega na wysyłaniu podstawowych poświadczeń uwierzytelniania HTTP (nazwa użytkownika i hasło), zanim serwer odpowie 401 pytaniem o nie. Może to zapisać żądanie podróży w obie strony podczas korzystania z aplikacji REST api, o których wiadomo, że wymagają podstawowego uwierzytelnienia.

Jak opisano w dokumentacji Spring , Apache HttpClient może być wykorzystany jako podstawowa implementacja do tworzenia żądań HTTP przy użyciu HttpComponentsClientHttpRequestFactory . HttpClient można skonfigurować tak, aby przeprowadzał wstępne zapobiegawcze uwierzytelnianie .

Następująca klasa rozszerza HttpComponentsClientHttpRequestFactory celu zapewnienia podstawowego zapobiegawczego uwierzytelniania.

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

Można to wykorzystać w następujący sposób:

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

Korzystanie z podstawowego uwierzytelnienia w HttpClient HttpComponent

Użycie HttpClient jako podstawowej implementacji RestTemplate do tworzenia żądań HTTP pozwala na automatyczną obsługę podstawowych żądań uwierzytelnienia (odpowiedź HTTP 401) podczas interakcji z interfejsami API. Ten przykład pokazuje, jak skonfigurować RestTemplate aby to osiągnąć.

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

Ustawianie nagłówków na żądanie Spring RestTemplate

Metody exchange RestTemplate pozwalają określić HttpEntity które zostaną zapisane w żądaniu podczas wykonywania metody. Możesz dodać nagłówki (taki klient użytkownika, strona odsyłająca ...) do tego obiektu:

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

Możesz także dodać przechwytywacz do RestTemplate jeśli chcesz dodać te same nagłówki do wielu żądań:

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

Ogólne wyniki z Spring RestTemplate

Aby RestTemplate mógł zrozumieć ogólną treść zwracaną, musimy zdefiniować odwołanie do typu wyniku.

org.springframework.core.ParameterizedTypeReference został wprowadzony od wersji 3.2

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

Przydałoby się np. List<User> z kontrolera.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow