2017-02-03 2 views
2

J'ai activé la compression de contenu sur mon application de démarrage du printemps et la réponse de chaque API est obtenir comprimé mais si je frappe ces APIS en utilisant RestTemplate-je obtenir le contenu commeAsyncRestTemplate Printemps ne fonctionne pas avec le contenu compressé, Mise en contenu compressé au lieu d'objet JSON

"\u001F�\b\u0000\u0000\u0000\u0000\u0000\u0000\u0000�}��8��¨OtD���1��]�m�mo��v�_LlP\u0014J�4E��(�����C�:\u0012<D\u0010����\b۲��\u0004\[email protected]\" 

Cependant, si j'utilise HttpClientBuilder.create().build() pour créer mon objet RestTemplate et ajouter headers.set("Content-Encoding", "gzip"); headers.set("Accept-Encoding", "gzip"); tout en fixant les en-têtes à ma demande d'échange, je reçois bon objet JSON dans un format de chaîne parce que l'API se retourne une chaîne.

Mais je suis confronté au même problème lors de l'accès à ces API en utilisant AsyncRestTemplate, même si je crée un objet AsyncRestTemplate en utilisant mon objet RestTemplate déjà présent. Une façon dont j'ai est de mettre en œuvre le pool de threads par moi-même, puis de répondre à la demande en utilisant RestTemplate, mais je veux savoir s'il existe un moyen d'obtenir un objet json au lieu du contenu compressé.

est le code complet

public class RestUtil { 

    @Resource RestTemplate restTemplate; 
    @Resource AsyncRestTemplate asyncRestTemplate; 

    private final Log log = LogFactory.getLog(getClass()); 

    public String getSyncResponse(HttpServletRequest request) { 
     final String URL = "not including url"; 

     UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(URL); 

     HttpEntity<String> entity = new HttpEntity<>(null, getHeaders(request)); 
     try { 
      ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), GET, entity, String.class); 
      System.out.println("==== sync response ===="); 
      System.out.println(response.getBody()); 
      System.out.println("========"); 
      return response.getBody(); 
     } catch (Exception ex) { 
      log.error("Error in connecting to codebook server ", ex); 
     } 
     return null; 
    } 

    public List<String> getAsyncResponse(HttpServletRequest request) { 

     List<String> urls = new ArrayList<>(); 
     urls.add("not including url"); 
     urls.add("not including url"); 

     HttpEntity<String> entity = new HttpEntity<>(null, getHeaders(request)); 
     try { 

      ArrayList<Future<ResponseEntity<String>>> futures = new ArrayList<>(); 

      for (String url : urls) { 
       ListenableFuture<ResponseEntity<String>> listenableFuture = asyncRestTemplate.exchange(url, GET, entity, String.class); 
       listenableFuture.addCallback(response -> log.info("Success"), ex -> log.error("Request failed", ex)); 
       futures.add(listenableFuture); 
      } 

      List<String> responses = new ArrayList<>(); 
      for (Future<ResponseEntity<String>> future : futures) { 
       responses.add(future.get().getBody()); 
      } 

      System.out.println("==== async response ===="); 
      System.out.println(responses); 
      System.out.println("========"); 

      return responses; 

     } catch (Exception ex) { 
      log.error("Error in connecting to server ", ex); 
     } 
     return null; 
    } 

    private HttpHeaders getHeaders(HttpServletRequest request) { 
     HttpHeaders headers = new HttpHeaders(); 
     headers.set("Accept", APPLICATION_JSON_UTF8_VALUE); 
     headers.set("Content-Type", APPLICATION_JSON_UTF8_VALUE); 
     headers.set("Content-Encoding", "gzip"); 
     headers.set("Accept-Encoding", "gzip"); 
     Enumeration<String> headerNames = request.getHeaderNames(); 
     while (headerNames.hasMoreElements()) { 
      String header = headerNames.nextElement(); 
      Enumeration<String> headerList = request.getHeaders(header); 
      headers.put(header, Collections.list(headerList)); 
     } 

     return headers; 
    } 
} 


@Configuration 
class HttpConfig { 

    @Bean 
    public RestTemplate restTemplate() { 
     RestTemplate restTemplate = new RestTemplate(httpRequestFactory()); 

     MappingJackson2HttpMessageConverter jsonHttpMessageConverter = new MappingJackson2HttpMessageConverter(); 
     jsonHttpMessageConverter.getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 
     restTemplate.getMessageConverters().add(jsonHttpMessageConverter); 

     return restTemplate; 
    } 

    @Bean 
    public ClientHttpRequestFactory httpRequestFactory() { 
     return new HttpComponentsClientHttpRequestFactory(httpClient()); 
    } 

    @Bean 
    public CloseableHttpClient httpClient() { 
     return HttpClientBuilder.create().build(); 
    } 

    @Bean 
    public AsyncRestTemplate asyncRestTemplate(AsyncClientHttpRequestFactory asyncHttpRequestFactory, RestTemplate restTemplate) { 
     return new AsyncRestTemplate(asyncHttpRequestFactory, restTemplate); 
    } 

    @Bean 
    public AsyncClientHttpRequestFactory asyncHttpRequestFactory() { 
     SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); 
     requestFactory.setTaskExecutor(new SimpleAsyncTaskExecutor()); 
     return requestFactory; 
    } 

} 

Répondre

1

Je Ci-dessous vous recommander faites, plutôt juste dire pas faire des compressions manuellement printemps faire pour vous (la compression fait sera fait par le serveur web (par exemple Tomcat) mais Spring le fera pour vous). Habituellement, au printemps de telles choses comme les compressions, le codage peut être activé simplement par la propriété unique

S'il vous plaît regarder http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#how-to-enable-http-response-compression

+0

oui je ne suis pas le faire manuellement, le printemps est fait pour moi, je viens d'écrire ces propriétés dans mon fichier application.properties server.compression.enabled = true server.compression.mime -types = application/javascript, application/x-javascript, application/json, application/xml, texte/html, text/xml, text/css, texte/plain –

2

Une solution simple est l'ajout d'un ResponseInterceptor avec AsyncRestTemplate, décompresse automatiquement que la réponse. L'ListenableFuture que vous recevez en retour aura déjà la réponse décompressée. Voici un exemple:

AsyncRestTemplate getAsyncRestTemplate() { 
    final HttpComponentsAsyncClientHttpRequestFactory httpComponentsAsyncClientHttpRequestFactory = 
      new HttpComponentsAsyncClientHttpRequestFactory(); 

    final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(httpComponentsAsyncClientHttpRequestFactory); 
    asyncRestTemplate.setInterceptors(Collections.singletonList((httpRequest, bytes, asyncClientHttpRequestExecution) -> { 
     if (!httpRequest.getHeaders().containsKey(HttpHeaders.ACCEPT_ENCODING)) { 
      httpRequest.getHeaders().set(HttpHeaders.ACCEPT_ENCODING, "gzip"); 
     } 
     final ListenableFuture<ClientHttpResponse> future = asyncClientHttpRequestExecution.executeAsync(httpRequest, bytes); 
     return new ListenableFutureAdapter<ClientHttpResponse, ClientHttpResponse>(future) { 
      @Override 
      protected ClientHttpResponse adapt(ClientHttpResponse clientHttpResponse) throws ExecutionException { 
       return new InflatedClientHttpResponse(clientHttpResponse); 
      } 
     }; 
    })); 
    return asyncRestTemplate; 

} 

public class InflatedClientHttpResponse implements ClientHttpResponse { 
    private final ClientHttpResponse clientHttpResponse; 
    private final Boolean isCompressed; 

    public InflatedClientHttpResponse(ClientHttpResponse clientHttpResponse) { 
     this.clientHttpResponse = clientHttpResponse; 
     final HttpHeaders httpHeaders = clientHttpResponse.getHeaders(); 

     final List<String> contentEncoding = httpHeaders.get(HttpHeaders.CONTENT_ENCODING); 
     if (contentEncoding != null && contentEncoding.contains("gzip")) { 
      isCompressed = true; 
     } else { 
      isCompressed = false; 
     } 

     httpHeaders.remove(HttpHeaders.CONTENT_ENCODING); 
     httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); 
    } 

    @Override 
    public HttpStatus getStatusCode() throws IOException { 
     return clientHttpResponse.getStatusCode(); 
    } 

    @Override 
    public int getRawStatusCode() throws IOException { 
     return clientHttpResponse.getRawStatusCode(); 
    } 

    @Override 
    public String getStatusText() throws IOException { 
     return clientHttpResponse.getStatusText(); 
    } 

    @Override 
    public void close() { 
     clientHttpResponse.close(); 
    } 

    @Override 
    public InputStream getBody() throws IOException { 
     if (isCompressed) { 
      return new GZIPInputStream(clientHttpResponse.getBody()); 
     } 
     return clientHttpResponse.getBody(); 
    } 

    @Override 
    public HttpHeaders getHeaders() { 
     return clientHttpResponse.getHeaders(); 
    } 
}