如何在 Spring 引导中使用 restTemplate 检索资源 object?
How do I retrieve Resource object using restTemplate in Spring Boot?
所以,基本上是标题。
我有 2 个微服务。一个生成并发送一个 zip 文件,另一个接收它,然后施展魔法,将其转换为字节数组 [],然后将其发送到其他地方。但这只是理论上的 - 我无法让它发挥作用。
我需要下载一个包含 InputStream 的资源 (https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/resources.html),我生成的 zip 存档被打包到其中。将它写在 HttpServletResponse 的 OutputStream 中对我不起作用,因为我无法使用它 - 稍后我需要操作文件,这种方法仅适用于浏览器下载 (?)
所以我在第一个微服务中这样做了:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
ZipOutputStream zos = new ZipOutputStream(bos);
try {
zos = service.generateZip(blablabla, zos);
baos.close();
bos.close();
zos.close();
} catch (Exception e) {
e.printStackTrace();
}
ByteArrayResource resource = new ByteArrayResource(baos.toByteArray());
ResponseEntity<Resource> response = ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/zip;charset=UTF-8"))
.contentLength(resource.contentLength())
.header(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.parse(format("attachment; filename=\"doc_%s.zip\"", id)).toString())
.body(resource);
第二个:
public byte[] getZip(DocRequest request) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/zip;charset=UTF-8"));
headers.setAccept(Collections.singletonList(MediaType.parseMediaType("application/zip;charset=UTF-8")));
// headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM));
Resource response = restTemplate.exchange(
apiUrl + "/doc/get-zip/" + request.getId(),
HttpMethod.GET,
new HttpEntity<>(null, headers),
Resource.class)
.getBody();
return (response != null) ? IOUtils.toByteArray(response.getInputStream()) : null;
}
还添加了 ResourceHttpMessageConverter 到 restTemplate 到两个微服务的配置:
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
converter.setObjectMapper(objectMapper);
ResourceHttpMessageConverter resourceConverter = new ResourceHttpMessageConverter();
resourceConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
return builder.interceptors(...)
.messageConverters(resourceConverter, converter)
.configure(restTemplate);
没有它们,我会收到如下所示的错误:
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0x59; nested exception is com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 middle byte 0x59\n at [Source: (ByteArrayInputStream); line: 1, column: 13]"}
或
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/zip;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 start byte 0x91; nested exception is com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 start byte 0x91\n at [Source: (ByteArrayInputStream); line: 1, column: 12]"}
取决于内容类型(分别为application/octet-stream和application/zip(application/zip;字符集=UTF-8))。
在我添加 ResourceHttpMessageConverter 之后,它现在给了我
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'PK\u0003..': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'PK\u0003...': was expecting ('true', 'false' or 'null')\n at [Source: (ByteArrayInputStream); line: 1, column: 28]"}
可能是我用错了?
任何意见,将不胜感激。提前谢谢你
最终将字节数组编码为 base64 字符串,然后将其作为
发送
return ResponseEntity.ok().body(Base64Utils.encodeToString(baos.toByteArray()));
然后在我的接收微服务中,我将以下内容添加到我的 restTemplate 配置中:
// idk if it's need to put StringHttpMessageConverter first in the list, but I did it just in case
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
成功了!
不知道对不对,但也许有人会觉得有用
所以,基本上是标题。
我有 2 个微服务。一个生成并发送一个 zip 文件,另一个接收它,然后施展魔法,将其转换为字节数组 [],然后将其发送到其他地方。但这只是理论上的 - 我无法让它发挥作用。
我需要下载一个包含 InputStream 的资源 (https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/resources.html),我生成的 zip 存档被打包到其中。将它写在 HttpServletResponse 的 OutputStream 中对我不起作用,因为我无法使用它 - 稍后我需要操作文件,这种方法仅适用于浏览器下载 (?)
所以我在第一个微服务中这样做了:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
ZipOutputStream zos = new ZipOutputStream(bos);
try {
zos = service.generateZip(blablabla, zos);
baos.close();
bos.close();
zos.close();
} catch (Exception e) {
e.printStackTrace();
}
ByteArrayResource resource = new ByteArrayResource(baos.toByteArray());
ResponseEntity<Resource> response = ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/zip;charset=UTF-8"))
.contentLength(resource.contentLength())
.header(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.parse(format("attachment; filename=\"doc_%s.zip\"", id)).toString())
.body(resource);
第二个:
public byte[] getZip(DocRequest request) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/zip;charset=UTF-8"));
headers.setAccept(Collections.singletonList(MediaType.parseMediaType("application/zip;charset=UTF-8")));
// headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM));
Resource response = restTemplate.exchange(
apiUrl + "/doc/get-zip/" + request.getId(),
HttpMethod.GET,
new HttpEntity<>(null, headers),
Resource.class)
.getBody();
return (response != null) ? IOUtils.toByteArray(response.getInputStream()) : null;
}
还添加了 ResourceHttpMessageConverter 到 restTemplate 到两个微服务的配置:
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
converter.setObjectMapper(objectMapper);
ResourceHttpMessageConverter resourceConverter = new ResourceHttpMessageConverter();
resourceConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
return builder.interceptors(...)
.messageConverters(resourceConverter, converter)
.configure(restTemplate);
没有它们,我会收到如下所示的错误:
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0x59; nested exception is com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 middle byte 0x59\n at [Source: (ByteArrayInputStream); line: 1, column: 13]"}
或
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/zip;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 start byte 0x91; nested exception is com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 start byte 0x91\n at [Source: (ByteArrayInputStream); line: 1, column: 12]"}
取决于内容类型(分别为application/octet-stream和application/zip(application/zip;字符集=UTF-8))。
在我添加 ResourceHttpMessageConverter 之后,它现在给了我
{"method":"POST","exceptionName":"RestClientException","detail":"Error while extracting response for type [interface org.springframework.core.io.Resource] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'PK\u0003..': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'PK\u0003...': was expecting ('true', 'false' or 'null')\n at [Source: (ByteArrayInputStream); line: 1, column: 28]"}
可能是我用错了? 任何意见,将不胜感激。提前谢谢你
最终将字节数组编码为 base64 字符串,然后将其作为
发送return ResponseEntity.ok().body(Base64Utils.encodeToString(baos.toByteArray()));
然后在我的接收微服务中,我将以下内容添加到我的 restTemplate 配置中:
// idk if it's need to put StringHttpMessageConverter first in the list, but I did it just in case
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
成功了!
不知道对不对,但也许有人会觉得有用