我有一个Servlet,返回的图像为InputStreamResource
。根据某些get query
参数,将返回大约50张静态图像。
由于不必在每次请求时都查找每个图像(这是很常见的),因此我想缓存这些图像响应。
@RestController
public class MyRestController {
//code is just example; may be any number of parameters
@RequestMapping("/{code}")
@Cachable("code.cache")
public ResponseEntity<InputStreamResource> getCodeLogo(@PathVariable("code") String code) {
FileSystemResource file = new FileSystemResource("d:/images/" + code + ".jpg");
return ResponseEntity.ok()
.contentType("image/jpg")
.lastModified(file.lastModified())
.contentLength(file.contentLength())
.body(new InputStreamResource(file.getInputStream()));
}
}
使用@Cacheable
注释时(无论是直接在RestMapping
方法上还是重构到外部服务),I_都会收到以下异常:
cause: java.lang.IllegalStateException: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times - error: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times
org.springframework.core.io.InputStreamResource.getInputStream(InputStreamResource.java:96)
org.springframework.http.converter.ResourceHttpMessageConverter.writeInternal(ResourceHttpMessageConverter.java:100)
org.springframework.http.converter.ResourceHttpMessageConverter.writeInternal(ResourceHttpMessageConverter.java:47)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:195)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:238)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
问题:那么我该如何缓存ResponseEntity
类型InputStreamResource
的呢?
高速缓存管理器将添加到高速缓存ResponseEntity
与InputStreamResource
它里面。第一次可以。但是当缓存ResponseEntity
将尝试InputStreamResouce
第二次读取时,您将获得异常,因为它无法多次读取流。
解决方案:不缓存InputStreamResouce
自身,而是缓存流的内容。
@RestController
public class MyRestController {
@RequestMapping("/{code}")
@Cachable("code.cache")
public ResponseEntity<byte[]> getCodeLogo(@PathVariable("code") String code) {
FileSystemResource file = new FileSystemResource("d:/images/" + code + ".jpg");
byte [] content = new byte[(int)file.contentLength()];
IOUtils.read(file.getInputStream(), content);
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_JPEG)
.lastModified(file.lastModified())
.contentLength(file.contentLength())
.body(content);
}
}
我使用过IOUtils.read()
from org.apache.commons.io
,将字节从流复制到数组,但是您可以通过任何首选方式来实现。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句