做了一个demo,放到码云上了,有兴趣的点我


一个良好的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的更多相关文章

  1. Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

    内容列表: 启用MVC Java config 或 MVC XML namespace 修改已提供的配置 类型转换和格式化 校验 拦截器 内容协商 View Controllers View Reso ...

  2. Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图

    接前面的Spring 4 官方文档学习(十一)Web MVC 框架,那篇太长,故另起一篇. 针对web应用的所有的MVC框架,都会提供一种呈现views的方式.Spring提供了view resolv ...

  3. Spring 4 官方文档学习(十一)Web MVC 框架

    介绍Spring Web MVC 框架 Spring Web MVC的特性 其他MVC实现的可插拔性 DispatcherServlet 在WebApplicationContext中的特殊的bean ...

  4. Spring 4 官方文档学习(十二)View技术

    关键词:view technology.template.template engine.markup.内容较多,按需查用即可. 介绍 Thymeleaf Groovy Markup Template ...

  5. Spring Boot 官方文档学习(一)入门及使用

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  6. Spring boot官方文档学习(一)

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  7. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  8. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

    本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...

  9. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(一)

    题外话:本篇是对之前那篇的重排版.并拆分成两篇,免得没了看的兴趣. 前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的 ...

  10. Spring 4 官方文档学习(十一)Web MVC 框架之编码式Servlet容器初始化

    在Servlet 3.0+ 环境中,你可以编码式配置Servlet容器,用来代替或者结合 web.xml文件.下面是注册DispatcherServlet : import org.springfra ...

随机推荐

  1. ERROR 1130 (HY000):Host'localhost'解决方法

    http://www.2cto.com/database/201211/169504.html ERROR 1130 (HY000):Host'localhost'解决方法   ERROR 1130 ...

  2. [git]git 分支

    什么动作,关键看你想完成什么 1. 添加新的远程分支: git push origin current_local_branch:new_remote_branch 2. 删除远程分支(冒号前必须要有 ...

  3. vim 学习日志(4):多窗口使用技巧

    原文地址: http://blog.csdn.net/devil_2009/article/details/7006113 vim多窗口使用技巧 1.打开多个窗口打开多个窗口的命令以下几个:横向切割窗 ...

  4. 动画_ _ Android应用开发之所有动画使用详解

    转载: http://blog.csdn.net/yanbober/article/details/46481171 题外话:有段时间没有更新博客了,这篇文章也是之前写了一半一直放在草稿箱,今天抽空把 ...

  5. mysq修改密码

    1.确定你的mysql 是否能正常工作登录数据库cmd--"命令提示字符"窗口录入,录入cd C:\mysql\bin 并按下回车键,将目录切换为 cd C:\mysql\bin再 ...

  6. Android中RelativeLayout各个属性的含义

    android:layout_above="@id/xxx"  --将控件置于给定ID控件之上android:layout_below="@id/xxx"  - ...

  7. VG vs SS WE vs IM [20160815]

    上单:慎,纳尔,艾克,艾瑞莉娅,普朗克 中单:弗拉基米尔,玛尔扎哈,卡尔玛,丽桑卓,索尔,崔斯特,辛德拉 打野:雷克赛,奈德丽,古拉加斯,伊莉丝,赫卡里姆,玛尔扎哈 下路:艾希,克格莫,烬,希维尔,布 ...

  8. 技术那么多,你想看看JSON Schema的测试吗?

    目录 1. 什么是JSON Schema? 2. 如何定义一个JSON Schema 3. 如何测试JSON Schema a) 使用JSON Schema validator GUI b) 在Jav ...

  9. 数据结构&算法-双向链表

    1.引言 双向链表原理和单链表差不多,就是操作相对繁琐一些,简单画了几个图,把思想弄清楚就好. 2.正文 这里介绍一下插入和删除的原理,相信这两个操作搞清楚的话,其他操作也没什么问题. 2.1插入节点 ...

  10. VC中GBK与UTF8转化

    void ConvertGBKToUtf8(CString& strGBK) {    int len=MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strG ...