Spring 4 官方文档学习(⑦)Web MVC 框架之HTTP caching support
来源:互联网 发布:2014年进出口数据 编辑:程序博客网 时间:2024/06/15 00:09
一个良好的HTTP缓存策略可以显著地增进web应用的性能和其客户端的体验。主要使用”Cache-Control” HTTP response header来完成,配合conditional headers例如”Last-Modified”和”ETag”。
“Cache-Control” HTTP response header 会建议私有缓存(如浏览器)和公开缓存(如代理)如何缓存HTTP response以供将来复用。
“ETag” (entity tag) 是由兼容HTTP/1.1 的web server返回的HTTP response header,用于判断给定URL的内容的改变。它可被认为是”Last-Modified” header的更复杂的继承者。 当服务器返回了一个带有ETag header的representation时,客户端可以在后续的GETs中使用该header -- 在一个”If-None_Match” header中。 如果内容没有改变,server会返回 “304: Not Modified”。
本部分描述了在一个Spring Web MVC 应用中配置HTTP caching的可行方式。
1、 Cache-Control HTTP header
Spring Web MVC支持很多使用环境和方式来配置一个应用的Cache-Control headers。RFC 7234 Section 5.2.2详细的描述了该header以及其可能的directives,有几种不同的方式来实现常用的案例。
Spring Web MVC 在其几个APIs中使用了一个配置惯例:setCachePeriod(int seconds) :
- -1 代表不会生成Cache-Control response header。
- 0 代表会阻止缓存,使用Cache-Control: no-store directive。
- n>0 会缓存给定的response,持续n秒,使用 Cache-Control: max-age=n directive。
CacheControl 构造类简单的描述了可用的 Cache-Control directives,可以更简单的build你自己的HTTP caching 策略。 一旦构造完毕,一个CacheControl实例可以在几个Spring Web MVC APIs中被用作参数。
- // Cache for an hour - "Cache-Control: max-age=3600"
- CacheControl ccCacheOneHour = CacheControl.maxAge(1, TimeUnit.HOURS);
- // Prevent caching - "Cache-Control: no-store"
- CacheControl ccNoStore = CacheControl.noStore();
- // Cache for ten days in public and private caches,
- // public caches should not transform the response
- // "Cache-Control: max-age=864000, public, no-transform"
- CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS)
- .noTransform().cachePublic();
2、支持静态资源的HTTP caching support
静态资源应该使用合适的 Cache-Control以及conditional headers来优化性能。 配置一个ResourceHttpRequestHandler来服务静态资源,不仅会天然地写入 Last-Modified headers (通过读取文件的metadata),还会写入 Cache-Control headers -- 如果正确的配置了。
你可以设置ResourceHttpRequestHandler的cachePeriod attribute 或者使用一个CacheControl实例,它们都可以支持更多特定的directives:
- @Configuration
- @EnableWebMvc
- public class WebConfig extends WebMvcConfigurerAdapter {
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/resources/**")
- .addResourceLocations("/public-resources/")
- .setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
- }
- }
在XML中:
- <mvc:resources mapping="/resources/**" location="/public-resources/">
- <mvc:cache-control max-age="3600" cache-public="true"/>
- </mvc:resources>
3、在Controllers中支持 Cache-Control、ETag、Last-Modified response headers
Controllers可以支持 Cache-Control、ETag、和/或 If-Modified-Since HTTP request;如果response设置了一个Cache-Control header,非常推荐这样做。这会计算给定request的一个lastModified long 和/或 一个Etag value,将其与 If-Modified-Since request header value作比较,并可能返回一个status code 304 (Not Modified) 的response。
如同在“Using HttpEntity”部分描述的,controllers可以使用HttpEntity 类型来与request/response 交互。
返回ResponseEntity的Controllers 可以在responses中以如下方式包含HTTP caching information:
- @GetMapping("/book/{id}")
- public ResponseEntity<Book> showBook(@PathVariable Long id) {
- Book book = findBook(id);
- String version = book.getVersion();
- return ResponseEntity
- .ok()
- .cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
- .eTag(version) // lastModified is also available
- .body(book);
- }
这样做,不仅会在response中带有ETag和Cache-Control headers,还会 将response转换成 一个响应体为空的HTTP 304 Not Modified response -- 如果客户端发送的conditional headers 匹配Controller设置的caching information。
一个@RequestMapping method 可能也会希望支持同样的行为。 可以这样做:
- @RequestMapping
- public String myHandleMethod(WebRequest webRequest, Model model) {
- long lastModified = // 1. application-specific calculation
- if (request.checkNotModified(lastModified)) {
- // 2. shortcut exit - no further processing necessary
- return null;
- }
- // 3. or otherwise further request processing, actually preparing content
- model.addAttribute(...);
- return "myViewName";
- }
这里有两个关键元素: 调用 request.checkNotModified(lastModified)、返回null。前者在其返回true之前设置了合适的response status和headers。后者,结合前者,会让Spring MVC 不再更进一步地处理该request。
注意,这里有3 个变体:
- request.checkNotModified(lastModified) 会比较lastModified 和 If-Modified-Since 或 If-Unmodified-Since request header。
- request.checkNotModified(eTag) 会比较 eTag 和 If-None-Match request header。
- request.checkNotModified(eTag, lastModified) 二者都比较,意味着两种条件应该都有效。
当接收 conditional GET/HEAD requests时, checkNotModified 会检查resource是否没有被修改;如果没有,它会返回一个HTTP 304 Not Modified response。
而在POST/PUT/DELETE requests时,checkNotModified 会检查resouce是否没有被修改;如果有修改,会返回一个HTTP 409 Precondition Failed response 来阻止并发修改。
4、Shallow ETag support
对于ETags的支持是由Servlet filter ShallowEtagHeaderFilter提供的。 这是一个简单的Servlet Filter,因此可与任何web框架结合使用。 ShallowEtagHeaderFilter filter 会创建 shallow ETags (与deep ETags相对,后面有讲)。 该filter会缓存被渲染的JSP的内容(或其他内容),生成一个MD5 hash,并将其返回作为response的一个ETag header。等下次客户端请求同样的资源时,它会使用该hash作为 If-None-Match value。 该filter会侦测到它,重新渲染视图,然后比较二者的hash。 如果相等,返回304。
注意,这种策略节省了网络带宽,而非CPU,因为仍然需要为每次request计算response。而controller级别的其他策略(上面讲过的),则既能节省带宽,又能避免计算。
该filter有一个writeWeakETag parameter,是用来配置该filter写入Weak ETags的,就像这样:W/"02a2d595e6ed9a0b24f027f2b63b134d6"
, 如同 RFC 7232 Section 2.3 中定义的一样。
你可以在web.xml中配置 ShallowEtagHeaderFilter:
- <filter>
- <filter-name>etagFilter</filter-name>
- <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
- <!-- Optional parameter that configures the filter to write weak ETags
- <init-param>
- <param-name>writeWeakETag</param-name>
- <param-value>true</param-value>
- </init-param>
- -->
- </filter>
- <filter-mapping>
- <filter-name>etagFilter</filter-name>
- <servlet-name>petclinic</servlet-name>
- </filter-mapping>
或者在Servlet 3.0+ 环境中:
- public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
- // ...
- @Override
- protected Filter[] getServletFilters() {
- return new Filter[] { new ShallowEtagHeaderFilter() };
- }
- }
See Section 22.15, “Code-based Servlet container initialization” for more details.
官方文档链接:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-caching
- Spring 4 官方文档学习(⑦)Web MVC 框架之HTTP caching support
- Spring 4 官方文档学习(⑥)Web MVC 框架之配置Spring MVC
- 18、Spring MVC 之 HTTP caching support
- Spring 4 官方文档学习(①)Web MVC 框架之异常处理
- Spring 4 官方文档学习(②)Web MVC 框架之编码式Servlet容器初始化
- 《Spring 5 官方文档》18. Web MVC 框架
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(4)
- Spring官方文档翻译——15.1 介绍Spring Web MVC框架
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(1)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(2)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(3)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(5)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(6)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(7)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(8)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(9)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(10)
- Spring 4.x官方参考文档中文版——第21章 Web MVC框架(11)
- SurfaceView
- Android GestureDetector手势识别
- KRpano 360° 旋转物体效果,插件
- Eclipse 教程
- win10 64系统如何换成win7 32系统?
- Spring 4 官方文档学习(⑦)Web MVC 框架之HTTP caching support
- JS引用类型深度拷贝浅拷贝
- Fiddler:显示请求花费的时间
- uboot的配置
- 20170305听课笔记(漫谈进程和线程)
- Intellij IDEA 十大快捷键
- Mac配置java_home找不到java路径的解决办法
- memcached主备方式部署
- 分表分页时查询用到的limit