Spring MVC 支持HTTP协议的 Last-Modified 缓存机制。

支持上次修改的HTTP请求,以方便内容缓存。 相同的合同作为Servlet API中的getLastModified方法。
通过委派到org.springframework.web.servlet.HandlerAdapter.getLastModified实施。 默认情况下,任何控制器或HttpRequestHandler Spring的默认框架内可以实现此接口,以实现最后修改时间检查。
注:另类处理的实现方法有不同的最后修改的处理方式。 例如,Spring 2.5的(使用注释的控制器的方法@RequestMapping )通过提供上次修改支持org.springframework.web.context.request.WebRequest.checkNotModified方法,允许主处理程序方法中最后一次修改检查。

在客户端地一次输入URL时,服务器端会返回内容和状态码200, 表示请求成功,同时会添加一个“Last-Modified”属性,表示该请求资源的最后修改时间
客户端第二次请求此URL时,客户端会向服务器发送请求头 “IF-Modified-Since”,如果服务端内容没有变化,则自动返回HTTP304状态码(只返回相应头信息,不返回资源文件内容,这样就可以节省网络带宽,提供响应速度和用户体验)
Spring MVC 中实现示例

UserCacheController.java
@Controller
public class UserCacheController extends AbstractController implements LastModified{private long lastModified = System.currentTimeMillis();protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception {List<User> userList = new ArrayList<User>();userList.add(new User("zhangsan", 18));userList.add(new User("wangwu", 16));System.out.println("执行一次,我有缓存");return new ModelAndView("userList", "users", userList);}@Overridepublic long getLastModified(HttpServletRequest request) {//时间戳逻辑,返回最后修改时间,例如if (lastModified == 0L) {lastModified = System.currentTimeMillis();}System.out.println("时间戳:"+lastModified);return lastModified;}
}

Spring MVC 提供的Last-Modified机制的支持,只需要实现LastModified接口,并实现

GetLastModified() 方法

相同的合同为的HttpServlet的getLastModified方法。 请求处理之前调用。
返回值将被发送到HTTP客户端作为Last-Modified头,并与如果-Modified-Since的标头,该客户端发回。 内容将只得到再生,如果出现了修改

每次修改资源的时候,更新下lastModified的值即可。

访问效果

只有第一次执行了Controller,以后访问都没执行Controller。

原理分析DispatcherServlet.doDispatch()

首先获取 http 请求的method type。
如果method 是 “GET”或“HEAD” 才支持缓存机制
通过 HandlerAdapter.getLastModified() 方法获取 UserCacheController 中的lastModified 的值,最后修改时间。
调用 checkNotModified() 方法验证 http 请求头中的“If-Modified-Since”的时间进行对比,判断页面是否更新过。如果有更新才执行具体的Controller, 没有更新则响应 304 状态码信息(HTTP 304: Not Modified )。
getLastModified()

通过handler的适配器类,然后在调用UserCacheController.getLastModified() 方法获取最后更新时间。

checkNotModified()
Paste_Image.png
调用 validateIfModifiedSince() 方法获取http请求头中的“If-Modified-Since”值,并验证是否修改过。
没有修改过则设置notModified=true,如果修改过则设置notModified=false。
如果 notModified=true,则设置response响应状态码304或412
如果是GET 或 HEAD 请求则添加响应头“Last-Modified”
validateIfModifiedSince()

解析http 请求头中的“If-Modified-Since”值
判断缓存页面是否需要更新。
注:(lastModifiedTimestamp / 1000 * 1000):因为http头中只保存到秒,所以这里把秒后面的置为0。
HTTP 请求响应头分析

通过浏览器F12 可以看出:

每次请求都会携带“If-Modified-Since”信息到服务器验证资源是否需要更新。
服务器响应头中会包含“Last-Modified”信息,访问资源最后修改的日期。
缓存限制条件

并非MappingHandler都支持缓存

比如:DefaultAnnotationHandlerMapping 就不支持缓存机制。
因为支持注解的Controller中可以有多个请求方法,而每个方法都需要计算文件的最后修改时间,这样LastModified就不适用了。只适用一个Controller中只支持一个请求的HandlerMapping。

AnnotationMethodHandlerAdapter

  • 方法永远返回-1。

    这个方法总是返回-1,因为带注解的控制器可以有许多方法,每个方法需要单独的上次更改时间的计算。 相反, RequestMapping注解的方法可以计算出上次更改时间值,调用org.springframework.web.context.request.WebRequest.checkNotModified(long) ,以检查它,并返回null如果返回true

SpringMVC源码解析之Last-Modified缓存机制相关推荐

  1. jquery源码解析:jQuery数据缓存机制详解2

    上一课主要讲了jQuery中的缓存机制Data构造方法的源码解析,这一课主要讲jQuery是如何利用Data对象实现有关缓存机制的静态方法和实例方法的.我们接下来,来看这几个静态方法和实例方法的源码解 ...

  2. 筑基期第一式:SpringMVC源码解析

    文章目录 SpringMVC源码解析 SPI机制 案例 SpringMVC中SPI的使用 初始化IOC容器与九大组件 初始化容器 初始化九大组件 小结 SpringMVC如何处理一个请求 doDisp ...

  3. 【kafka】Kafka 源码解析:Group 协调管理机制

    1.概述 转载:Kafka 源码解析:Group 协调管理机制 在 Kafka 的设计中,消费者一般都有一个 group 的概念(当然,也存在不属于任何 group 的消费者),将多个消费者组织成一个 ...

  4. SpringMVC源码解析

     一:springmvc运行过程: 1. dispatcherServlet 通过 HandlerMapping 找到controller 2. controller经过后台逻辑处理得到结果集mode ...

  5. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  6. Android View体系(五)从源码解析View的事件分发机制

    Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源码解析Sc ...

  7. SpringMVC源码解析(四)——请求处理

    2019独角兽企业重金招聘Python工程师标准>>> 前言 这一篇,将着手介绍一次请求的处理.用到了 HandlerMapping.HandlerAdapter 知识,如果遇到不是 ...

  8. brpc源码解析(四)—— Bthread机制

    目录 一.概述 二.启动入口函数 三.内部启动函数 四.worker工作入口 五.总结 Bthread是brpc用到的一个线程库,也是brpc的核心之一,默认情况下,包括用户代码在内的绝大部分代码都是 ...

  9. SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver

    HandlerMethodArgumentResolver主要负责执行handler前参数准备工作. 看个例子,红色部分的id初始化,填充值就是它干的活: 1 @RequestMapping(valu ...

最新文章

  1. 如何找到文件的家-打开文件对话框openFileDialog
  2. C#解析XML各种方法特点比较(转载)
  3. linux下软件如何防破裂,linux下管道破裂的處理
  4. Lync通过IP地址网段显示地理位置
  5. 大家在寻找的高级程序员到底是什么样子的?
  6. 使用Spring Boot构建RESTFul服务
  7. U盘 制作 win 7 64bit 旗舰版 安装盘
  8. 漫步最优化四——约束
  9. 华为Mate8刷低Android版本,华为mate8怎么刷机 华为mate8刷机方法【图文教程】
  10. sql 占比计算_数据库索引的优化及SQL处理过程(建议收藏)
  11. 地图Web服务API接口——搜索POI(以高德地图为例)
  12. 用idea创建vue项目
  13. 杀毒软件误删文件了怎么办?如何恢复被杀毒软件删除的文件
  14. 阿里云注册域名,购买云服务器,备案,域名解析教程
  15. 没有对比就没有伤害:《明日之后》竟成最良心国产末日手游?
  16. Oracle错误08s01,Java7 sqljdbc4 – getConnection()上的SQL错误08S01
  17. 论文排版——Latex页眉页脚设定(中英都可以适用)
  18. [原创]服装鞋帽企业配送中心优化方案 WMS仓储管理系统
  19. Java课程设计基于SSM的出租房管理
  20. 台式计算机用u盘给电脑安装系统,台式电脑怎么用U盘重装Win7系统

热门文章

  1. 烤仔星选创作计划 | Conflux X Odaily 星球君,让每一颗星星都闪亮
  2. matlab中gad,10大经典算法matlab代码以及代码详解【数学建模、信号处理】
  3. Fonticon在企业移动APP开发中的应用研究
  4. 2016源创会深圳站—网易蜂巢架构
  5. 关于HTC Touch Diamond 2的ROM和WM软件开发高手看过来…
  6. Java编程基础:学习IO流
  7. 收集的几种exe嵌入网页的方法(1)
  8. C/C++ 获取系统时间距 1970年1月1日00:00:00 的毫秒数
  9. 如何在Mac,iPhone或iPad上标记文件
  10. win10 更新后不能切换输入法怎么办 win10输入法切换不了怎么解决