2016-06-09 230 views
2

我有一個Java應用程序構建在Spring 3.2.0執行外部調用REST api服務JSON數據。Gzip壓縮與MockRestServiceServer

該呼叫由Spring RestTemplate類執行,傑克遜 2.2.3作爲串行器/解串器。

該調用是函數式的,並支持普通和gzip壓縮響應。

爲了Junit測試呼叫,我使用MockRestServiceServer。一切正常,直到我嘗試引入gzip壓縮。我無法在官方文檔如何激活MockRestServiceServer gzip壓縮找到,讓我去手動路線:

  • 手動gzip壓縮響應的字符串內容

  • 設置「內容編碼「以‘在報頭壓縮程序’

不幸的是,我一次又一次地得到了同樣的錯誤,反序列化響應主體時,傑克遜拋出:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Illegal character ((CTRL-CHAR, code 31)): 
only regular white space (\r, \n, \t) is allowed between tokens 
at [Source: [email protected]; line: 1, column: 2]; 
nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): 
only regular white space (\r, \n, \t) is allowed between tokens 

下面是當前代碼(由於修改,以企業數據......)

測試類

public class ImportRefCliCSTest { 

    @Autowired 
    private MyService myService; 

    private MockRestServiceServer mockServer; 

    @Before 
    public void before() { 
     mockServer = MockRestServiceServer.createServer(myService.getRestTemplate()); 
    } 

    @Test 
    public void testExternalCall() throws IOException { 

     String jsonData = "[{\"testing\":\"Hurray!\"}]"; 
     HttpHeaders headers = new HttpHeaders(); 
     headers.add("Content-Encoding", "gzip"); 

     DefaultResponseCreator drc = withSuccess(gzip(jsonData), 
      MediaType.APPLICATION_JSON).headers(headers); 

     mockServer.expect(requestTo(myService.EXTERNAL_CALL_URL)) 
      .andExpect(method(HttpMethod.GET)).andRespond(drc); 

     myService.performCall(); 
    } 


    private static String gzip(String str) throws IOException { 
     if (str == null || str.length() == 0) { 
      return str; 
     } 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     GZIPOutputStream gzip = new GZIPOutputStream(out); 
     gzip.write(str.getBytes()); 
     gzip.close(); 
     String outStr = out.toString(); 
     return outStr; 
    } 
} 

服務類

@Service 
public class MyService { 

    public static final String EXTERNAL_CALL_URL = "<myURL>"; 
    private RestTemplate restTemplate; 

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


    public void performCall() { 

     try { 
      HttpHeaders requestHeaders = new HttpHeaders(); 
      requestHeaders.add("Accept-Encoding", "gzip"); 
      HttpEntity<MyObject[]> requestEntity = new HttpEntity<MyObject[]>(requestHeaders); 

      ResponseEntity<MyObject[]> responseEntity = restTemplate.exchange(
       EXTERNAL_CALL_URL, HttpMethod.GET, requestEntity, MyObject[].class); 
      MyObject[] array = responseEntity.getBody(); 
      if (array == null || array.length == 0) { 
       return null; 
      } 
      return null; 
     } catch (RestClientException e) { 
      return null; 
     } 
    } 

    public RestTemplate getRestTemplate(){ 
     return restTemplate; 
    } 
} 

我覺得我錯過了一些東西。手動gzip壓縮似乎相當可疑。

有沒有人有這個想法?

在此先感謝您的答案!

回答

0

當程序將gzip內容轉換爲字符串時,某些字節會摺疊。所以客戶端不能解壓縮並拋出異常。解決方案是返回byte[]

private static byte[] gzip(String str) throws IOException { 
    if (str == null || str.length() == 0) { 
     return new byte[0]; 
    } 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    GZIPOutputStream gzip = new GZIPOutputStream(out); 
    gzip.write(str.getBytes());//consider to use str.getBytes("UTF-8") 
    gzip.close(); 
    return out.toByteArray(); 
} 
+0

嗨@beckyang。謝謝您的回答。我會嘗試這個並回到你身邊 –