SpringMVC源码解析之Last-Modified缓存机制

简介: SpringMVC源码解析之Last-Modified缓存机制

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);
    }
    @Override
    public 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的标头,该客户端发回。 内容将只得到再生,如果出现了修改

image.png

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


目录
相关文章
|
8月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2123 1
|
7月前
|
缓存 并行计算 PyTorch
PyTorch CUDA内存管理优化:深度理解GPU资源分配与缓存机制
本文深入探讨了PyTorch中GPU内存管理的核心机制,特别是CUDA缓存分配器的作用与优化策略。文章分析了常见的“CUDA out of memory”问题及其成因,并通过实际案例(如Llama 1B模型训练)展示了内存分配模式。PyTorch的缓存分配器通过内存池化、延迟释放和碎片化优化等技术,显著提升了内存使用效率,减少了系统调用开销。此外,文章还介绍了高级优化方法,包括混合精度训练、梯度检查点技术及自定义内存分配器配置。这些策略有助于开发者在有限硬件资源下实现更高性能的深度学习模型训练与推理。
1450 0
|
4月前
|
JSON 前端开发 Java
Spring MVC 核心组件与请求处理机制详解
本文解析了 Spring MVC 的核心组件及请求流程,核心组件包括 DispatcherServlet(中央调度)、HandlerMapping(URL 匹配处理器)、HandlerAdapter(执行处理器)、Handler(业务方法)、ViewResolver(视图解析),其中仅 Handler 需开发者实现。 详细描述了请求执行的 7 步流程:请求到达 DispatcherServlet 后,经映射器、适配器找到并执行处理器,再通过视图解析器渲染视图(前后端分离下视图解析可省略)。 介绍了拦截器的使用(实现 HandlerInterceptor 接口 + 配置类)及与过滤器的区别
396 0
|
9月前
|
机器学习/深度学习 存储 缓存
LLM高效推理:KV缓存与分页注意力机制深度解析
随着大型语言模型(LLM)规模和复杂性的增长,高效推理变得至关重要。KV缓存和分页注意力是优化LLM推理的两项关键技术。KV缓存通过存储键值对减少重复计算,而分页注意力则通过将序列分割成小块来降低内存消耗,从而有效处理长序列。本文深入剖析这些技术的工作原理及其在仅解码器模型中的应用,探讨其优势与挑战,并展示其实现示例。
513 16
LLM高效推理:KV缓存与分页注意力机制深度解析
|
10月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
12198 46
|
10月前
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
326 18
|
9月前
|
存储 缓存 分布式计算
【赵渝强老师】Spark RDD的缓存机制
Spark RDD通过`persist`或`cache`方法可将计算结果缓存,但并非立即生效,而是在触发action时才缓存到内存中供重用。`cache`方法实际调用了`persist(StorageLevel.MEMORY_ONLY)`。RDD缓存可能因内存不足被删除,建议结合检查点机制保证容错。示例中,读取大文件并多次调用`count`,使用缓存后执行效率显著提升,最后一次计算仅耗时98ms。
260 0
【赵渝强老师】Spark RDD的缓存机制
|
9月前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
470 1
|
11月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
11月前
|
存储 前端开发 Java
【SpringMVC】——Cookie和Session机制
获取URL中参数@PathVarible,上传文件@RequestPart,HttpServerlet(getCookies()方法,getAttribute方法,setAttribute方法,)HttpSession(getAttribute方法),@SessionAttribute
495 11

推荐镜像

更多
  • DNS