Suche…


Eine große Datei herunterladen

Die Methoden getForObject und getForEntity von RestTemplate laden die gesamte Antwort in den Speicher. Dies ist nicht zum Herunterladen großer Dateien geeignet, da dies zu Speicherausnahmen führen kann. Dieses Beispiel zeigt, wie die Antwort einer GET-Anforderung gestreamt wird.

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

Beachten Sie, dass Sie den InputStream nicht einfach aus dem Extraktor zurückgeben können, da die zugrunde liegende Verbindung und der Stream bei der Rückkehr der Ausführungsmethode bereits geschlossen sind.

Verwenden der preemptiven Basisauthentifizierung mit RestTemplate und HttpClient

Präemptive Basisauthentifizierung ist die Praxis, HTTP-Basisauthentifizierungsanmeldeinformationen (Benutzername und Kennwort) zu senden, bevor ein Server mit einer 401 Antwort antwortet, die nach ihnen fragt. Dies kann eine Rundreise für eine Anforderung ersparen, wenn REST-Apis konsumiert werden, von denen bekannt ist, dass sie eine Basisauthentifizierung erfordern.

Wie in der Spring-Dokumentation beschrieben , kann Apache HttpClient als zugrunde liegende Implementierung zum Erstellen von HTTP-Anforderungen mithilfe von HttpComponentsClientHttpRequestFactory . HttpClient kann für die präemptive Basisauthentifizierung konfiguriert werden.

Die folgende Klasse erweitert HttpComponentsClientHttpRequestFactory um eine präemptive Basisauthentifizierung.

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

Dies kann wie folgt verwendet werden:

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

Verwenden der Basisauthentifizierung mit dem HttpClient von HttpComponent

Wenn Sie HttpClient als RestTemplate -zugrunde liegende Implementierung zum Erstellen von HTTP-Anforderungen verwenden, können Sie bei der Interaktion mit APIs grundlegende Authentifizierungsanforderungen (eine Antwort von http 401) automatisch RestTemplate . Dieses Beispiel zeigt, wie eine RestTemplate konfiguriert RestTemplate , um dies zu erreichen.

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

Festlegen von Headern für die Spring RestTemplate-Anforderung

Mit den exchange von RestTemplate können Sie ein HttpEntity angeben, das beim Ausführen der Methode in die Anforderung geschrieben wird. Sie können dieser Entität Header hinzufügen (z. B. User Agent, Referrer ...):

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

Sie können auch einen Interceptor zu Ihrer RestTemplate wenn Sie mehreren Anfragen die gleichen Header hinzufügen müssen:

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-Ergebnisse von Spring RestTemplate

Damit RestTemplate generischen Inhalt des zurückgegebenen Inhalts verstehen kann, müssen wir die Referenz des Referenztyps definieren.

org.springframework.core.ParameterizedTypeReference wurde seit 3.2 eingeführt

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

Kann nützlich sein, um zB List<User> von einem Controller abzurufen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow