我有一个spring XML MVC rest服务,它以XML格式返回数据。我想缓存这个xml响应。我怎样才能做到这一点?是否可以使用mvc:interceptors?
执行此操作答案 0 :(得分:5)
你可以做到这一点,但我认为有更好的解决方案。
首先,如果你想使用Spring MVC拦截器,你将使用postHandle方法在缓存中存储一些东西,使用preHandle来检查缓存和可能的规避处理。问题是,你在缓存中存储了什么。您需要存储完整的响应。这意味着你必须在postHandle中轻松获得ModelAndView的完整响应。这可能会也可能不容易,这取决于你的工作方式。
最好总是使用不同的缓存机制。我建议在Web服务器级别进行缓存。如果您希望在拦截器级别缓存,因为它正好在Web服务器的“下一步”,并且我认为在那里重新发明轮子没有任何好处。 Apache有一个缓存模块。 nginx也是如此。清漆也非常棒。
我还应该提到,在确定需要(不要过早优化)之前,不应该缓存。这浪费你的时间和精力。其次,当您确定存在需要修复的性能问题(并且缓存是正确的解决方案)时,您应该将正确的数据缓存在正确的位置。
现在,假设您确定存在性能问题,某种缓存是一个很好的解决方案。接下来要确定的是可以缓存的内容。如果,对于每个URL,您返回相同的数据,那么在Web服务器(Apache,nginx,Varnish等)级别进行缓存将是您最好的选择。
通常,您会遇到两个客户端将访问相同的URL并获取不同数据的情况。这在Facebook这样的网站上最容易看到。我登录时看到的数据与朋友看到的数据不同。在这种情况下,您将无法在Web服务器级别进行缓存。您需要在应用程序内部进行缓存。通常这意味着在数据库级别进行缓存。
答案 1 :(得分:4)
我不能不同意解决方案的优化部分。
当您从远离千里之外的远程位置加载数据时,Web请求本质上很慢。每个呼叫必须至少对数据包本身进行完整的TCP往返时间,可能是每个请求的连接和fin,在开始传输数据之前连接是三包同步交换。
美国沿海到海岸的延迟时间约为50毫秒,因此每个连接都会受到150毫秒的惩罚,这对于大多数实施来说都是针对每个请求而产生的。
在客户端缓存响应会完全消除此延迟,如果服务在响应中具有正确的标头,则很简单。如果他们不这样做,您将不得不定义缓存策略,这在很大程度上并不是特别困难。大多数API调用都是实时的或不是。
在我看来,缓存REST响应不是过早优化,这是常识。
答案 2 :(得分:4)
不要使用弹簧缓存,这不是你需要的。您需要减少服务器的负载,而不是加快内部弹簧应用程序的执行速度。
尝试使用som HTTP相关的缓存策略。
您可以在请求中添加一个HTTP标头
#cache expires in 3600 seconds
cache-control: private, max-age=3600
#hash of your content
ETag: "e6811cdbcedf972c5e8105a89f637d39-gzip"
# redirect caching to any HTTP header
vary: User-Agent
Detailed description of caching techniques
春天的例子
@RequestMapping (value = "/resource/1.pdf", produces = "application/octet-stream")
public ResponseEntity<InputStreamResource> getAttachement (@RequestParam (value = "id") Long fileId)
{
InputStreamResource isr = new InputStreamResource(javaInputStream);
HttpHeaders headers = new HttpHeaders();
//other headers
headers.setCacheControl("private, max-age=3600");
return new ResponseEntity<>(irs, headers, HttpStatus.OK);
}
答案 3 :(得分:3)
我使用它并且它以极快的速度工作。 真的很容易使用spring + ehcache:
1)控制器:
@Cacheable("my.json")
@RequestMapping("/rest/list.json")
public ResponseEntity list(@RequestParam(value = "page", defaultValue = "0", required = false)
int pageNum,
@RequestParam(value = "search", required = false)
String search) throws IOException {
...
}
2)在ehcache.xml上,有人喜欢这样:
<cache name="my.json" maxElementsInMemory="10000" eternal="true" overflowToDisk="false"/>
3)配置弹簧。我正在使用spring javaconf风格:
@Configuration
@EnableCaching
public class ApplicationConfiguration {
@Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() throws MalformedURLException {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return ehCacheManagerFactoryBean;
}
@Bean
@Autowired
public EhCacheCacheManager cacheManager(EhCacheManagerFactoryBean ehcache) {
EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
ehCacheCacheManager.setCacheManager(ehcache.getObject());
return ehCacheCacheManager;
}
}
答案 4 :(得分:0)
在应用程序级别,我会使用普通的Java缓存作为EHCache。 EHCache很容易与Spring bean上的方法集成。您可以将服务方法注释为@Cacheable
并完成。请查看EHCache Spring Annotations。
在HTTP级别,Spring MVC提供了一个有用的ETag filter。但我认为如果你能在服务器级别配置这种缓存比在应用程序级别更好,那会更好。
答案 5 :(得分:-1)
从Spring 3.1开始,您可以使用@Cachable注释。还支持条件缓存,以及一些兄弟注释,如@CachePut,@CacheEvict和@Caching,用于更细粒度的控制。
Spring目前支持两个不同的cache managers,一个由ConcurrentHashMap
支持,另一个由 Ehcache 支持。
最后,请不要忘记阅读有关如何enable注释的详细信息。