2015-12-22 15 views
5

Dopo ho modificato Consuming a RESTful Web Service esempio per chiamare get users by id da api.stackexchange.com ottengo JsonParseException:come analizzare gzip risposta codificato con RestTemplate dalla primavera-Web

com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens

risposta da api.stackexchange.com è compresso gzip.

Come aggiungere supporto per la risposta compressa gzip in RestTemplate di Spring-Web?

Sto usando Spring boot parent ver. 1.3.1.RELEASE quindi Primavera-Web 4.2.4-RELEASE

Ecco il mio esempio rettificato:

User.java

package stackexchange.dto; 

import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 
import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy; 
import com.fasterxml.jackson.databind.annotation.JsonNaming; 

@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonNaming(LowerCaseWithUnderscoresStrategy.class) 
public class User { 

    // Properties made public in order to shorten the example 
    public int userId; 
    public String displayName; 
    public int reputation; 

    @Override 
    public String toString() { 
     return "user{" 
       + "display_name='" + displayName + '\'' 
       + "reputation='" + reputation + '\'' 
       + "user_id='" + userId + '\'' 
       + '}'; 
    } 
} 

CommonWrapper.java

package stackexchange.dto; 

import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 
import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy; 
import com.fasterxml.jackson.databind.annotation.JsonNaming; 

@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonNaming(LowerCaseWithUnderscoresStrategy.class) 
public class CommonWrapper { 

    // Properties made public in order to shorten the example 
    public boolean hasMore; 
    // an array of the type found in type 
    public User[] items; 
    public int page; 
    public int pageSize; 
    public int quotaMax; 
    public int quotaRemaining; 

    @Override 
    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     for (User user : items) { 
      sb.append("{" + user.toString() + "}\n"); 
     } 

     return "common_wrapper{" 
     + "\"items\"=[\n" 
     + sb 
     + "]" 
     + "has_more='" + hasMore + '\'' 
     + "page='" + page + '\'' 
     + "page_size='" + pageSize + '\'' 
     + "quota_max='" + quotaMax + '\'' 
     + "quota_remaining='" + quotaRemaining + '\'' 
     + '}'; 
    } 
} 

StackExchange.java

package stackexchange; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.boot.CommandLineRunner; 
import org.springframework.boot.SpringApplication; 
import org.springframework.web.client.RestTemplate; 

import stackexchange.dto.CommonWrapper; 

import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy; 
import com.fasterxml.jackson.databind.annotation.JsonNaming; 

@JsonNaming(LowerCaseWithUnderscoresStrategy.class) 
public class StackExchange implements CommandLineRunner{ 

    private static final Logger log = LoggerFactory.getLogger(StackExchange.class); 

    public static void main(String args[]) { 
     SpringApplication.run(StackExchange.class); 
    } 

    @Override 
    public void run(String... strings) throws Exception { 

     RestTemplate restTemplate = new RestTemplate(); 
     CommonWrapper response = restTemplate 
       .getForObject(
         "https://api.stackexchange.com/2.2/users/4607349?site=stackoverflow", 
         CommonWrapper.class); 

     log.info(response.toString()); 
    } 

} 

pom.xml - come nell'esempio

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>stackexchangetest</groupId> 
    <artifactId>stackexchangetest</artifactId> 
    <version>0.0.1</version> 
    <name>stackexchangetest</name> 
    <description>api.stackexchange.com Test</description> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.3.1.RELEASE</version> 
    </parent> 

    <properties> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-web</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 

</project> 
+1

avete fatto leggi il documento: http://docs.spring.io/autorepo/docs/spring-android/1.0.x/reference/html/rest-template.html#d4e395 ??? – ben75

+0

Sì, l'ho letto. È la soluzione per Spring Android, mentre io uso Spring Web. 'HttpHeaders' non contiene il metodo' setAcceptEncoding' in Spring Web. Lo dirò nella domanda per evitare confusione. Thx –

+0

Mi piace quanto sia meticolosa questa domanda. –

risposta

18

Sostituire requestFactory default con Apache HttpClient:

HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
      HttpClientBuilder.create().build()); 
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory); 

Aggiungi Apache Http client in pom.xml

<dependency> 
    <groupId>org.apache.httpcomponents</groupId> 
    <artifactId>httpclient</artifactId> 
    <!--Version is not needed when used with Spring Boot parent pom file --> 
    <version>4.5.1</version> 
</dependency> 
+0

Grazie Michal ha funzionato. La documentazione usuale descrive Android non Spring Web come hai detto. Perché non aggiungi anche riferimenti se esiste un blog o un link per questo? –

+0

Grande, sono felice di poterti aiutare. Non ho trovato nessun articolo o post sul blog in quel momento. Sentiti libero di documentarlo e lascia che Google lo indicizzi correttamente, in modo che nessuno possa lottare di nuovo :) –

+0

Ciao Michal sei a conoscenza di qualsiasi svantaggio dell'uso di HttpComponentsClientHttpRequestFactory in ambiente multithread. Intendo quando i risultati degli utenti sono molto alti. –

1
private String callViaRest(String requestString, Steps step) { 
    HttpHeaders headers = new HttpHeaders(); 
    headers.setContentType(MediaType.TEXT_XML); 
    headers.add("Accept-Encoding", "application/gzip"); 
    HttpEntity<String> entity = new HttpEntity<String>(requestString, headers); 

    byte[] responseBytes = jsonRestTemplate 
      .exchange("yourUrl", HttpMethod.POST, entity, byte[].class).getBody(); 
    String decompressed = null; 
    try { 
     decompressed= new String(CompressionUtil.decompressGzipByteArray(responseBytes),Charsets.UTF_8); 
    } catch (IOException e) { 
     LOGGER.error("network call failed.", e); 
    } 
    return decompressed; 
} 
+0

Aggiungi dipendenza per org.apache.commons.jcs a pom. import org.apache.commons.jcs.utils.zip.CompressionUtil; –

+0

aggiungendo headers.add ("Accept-Encoding", "application/gzip"); lavorando per me grazie per la soluzione. –

Problemi correlati