2015-12-22 13 views
5

Nachdem ich geändert Consuming a RESTful Web Service Beispiel analysieren zu nennen get users by id von api.stackexchange.com ich JsonParseException:Wie gzip codierte Antwort mit RestTemplate von Spring-Web

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

Antwort von api.stackexchange.com wird komprimiert gzip.

Wie kann die Unterstützung für die komprimierte gzip-Antwort in Spring-Web RestTemplate hinzugefügt werden?

Ich benutze Spring Boot Eltern ver. 1.3.1.RELEASE daher Frühlings-Web 4.2.4-RELEASE

Hier ist mein bereinigtes Beispiel:

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 - wie in Beispiel

<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

haben Sie Lesen Sie das Dokument: http://docs.spring.io/autorepo/docs/spring-android/1.0.x/reference/html/rest-template.html#d4e395 ??? – ben75

+0

Ja, ich habe es gelesen. Es ist eine Lösung für Spring Android, während ich Spring Web verwende. 'HttpHeaders' enthält keine 'setAcceptEncoding'-Methode in Spring Web. Ich werde es in der Frage angeben, um Verwirrung zu vermeiden. Thx –

+0

Ich liebe, wie Meta diese Frage ist. –

Antwort

18

Standard requestFactory mit Apache Httpclient ersetzen:

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

Client-Apache Http Fügen Sie 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

Danke Michal es hat funktioniert. Normale Dokumentation beschreiben Android nicht Spring Web, wie Sie sagten. Warum fügst du auch keine Referenz hinzu, wenn es einen Blog oder einen Link dafür gibt? –

+0

Großartig, ich bin glücklich, ich könnte helfen. Ich habe zu dem Zeitpunkt keinen Artikel oder Blogeintrag gefunden. Fühlen Sie sich frei, es zu dokumentieren und lassen Sie Google es richtig indizieren, damit niemand wieder kämpfen wird :) –

+0

Hi Michal sind Sie irgendwelche Nachteil der Verwendung von HttpComponentsClientHttpRequestFactory in Multithread-Umgebung bewusst. Ich meine, wenn die Treffer von Nutzern sehr hoch sind. –

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

Fügen Sie die Abhängigkeit für org.apache.commons.jcs zu pom hinzu. import org.apache.commons.jcs.utils.zip.CompressionUtil; –

+0

durch Hinzufügen von headers.add ("Accept-Encoding", "application/gzip"); Arbeiten für mich Danke für die Lösung. –

Verwandte Themen