2016-06-09 173 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。谢谢您的回答。我会尝试这个并回到你身边 –