【问题标题】:Force Browser to cache JS response from Spring MVC强制浏览器缓存来自 Spring MVC 的 JS 响应
【发布时间】:2012-07-25 09:38:44
【问题描述】:

每当我需要处理 Spring MVC 上的自定义响应数据类型时,这似乎有些尴尬。

就我而言,我需要返回一个 JavaScript 内容。但是,我希望它是缓存。

所以澄清一下,这不是一个静态文件案例 (<mvc:resources...),而是一个在服务器上生成的动态文件,我确实想要缓存它(即 HttpResponse 200 和 HttpResponse 302)。

就代码而言,在客户端我只有:

<script src="<spring:url value='/some-file.js'/>"></script>

比 SpringMVC 控制器:

@RequestMapping(value = "/some-file.js")
public ResponseEntity<String> resourceBundles(HttpServletRequest request, HttpServletResponse response, Locale locale) throws IOException {

    responseHeaders.add("Cache-Control", "public, max-age");
    responseHeaders.add("Content-Type", "text/javascript; charset=UTF-8");
    responseHeaders.add("Expires", "max-age");

    // Turn this into JSON response:
    String someJson = "{ a:a, b;b};";
    return new ResponseEntity<String>("var data = " + someJson, responseHeaders,  HttpStatus.OK);
}

但是,浏览器似乎总是试图访问这个动态 JS 文件。

由于这个文件是 Session 依赖的,所以我无法生成它并将其视为静态文件。

有什么建议吗?

【问题讨论】:

标签: java json spring spring-mvc


【解决方案1】:

这是正确的行为。大多数浏览器会向您发送带有If-Modified-Since + 时间戳的GET 请求,以检查文件是否已更改。

在通常情况下,您会使用时间戳来确定文件是否已更改。但由于您的情况永远不会改变,您可以回复304 / HttpStatus.NOT_MODIFIED response without a response body(而不是200/OK)。

这告诉浏览器文件没有改变。

这应该可行:

@RequestMapping(value = "/some-file.js")
public ResponseEntity<String> resourceBundles(
    HttpServletRequest request, 
    HttpServletResponse response, Locale locale) throws IOException {

    Date lmod = session.getAttribute("lmod");
    if( null == lmod ) {
        lmod = new Date();
        session.setAttribute("lmod", lmod);
    }

    responseHeaders.add("Last-Modified", lmod);

    String ifModifiedSince = request.getHeader("If-Modified-Since");
    if( null != ifModifiedSince ) { // You may want to compare lmod and ifModifiedSince here, too
        return new ResponseEntity( responseHeaders, HttpStatus.NOT_MODIFIED );
    }

    ... create first time response ...
}

告诉浏览器Last-Modified将使它能够向您发送If-Modified-Since

【讨论】:

  • 谢谢。逻辑对我来说很清楚,但我不清楚如何根据客户的请求创建一个机制来回复 200 或 304。在 chrome 中测试这个,我没有看到 If-Modified-Sinse 被发送。
  • 感谢您的努力。这或多或少是我尝试过的,但 isModifiedSince 在所有情况下都是空的。我用所有浏览器对其进行了测试,以查看类似的行为。使用 chrome,我可以清楚地看到这个“动态”JS 不发送此标头,而位于 mvc:resources 路径中的其他 JS 发送 If-Modified-Since。我会检查是否可以将此路径添加到 mvc:resources 组。
  • 确保max-age 有效(即具有最大年龄;仅提供字符串只会混淆浏览器)。如果 JS 文件包含在带有 script 元素的页面中,浏览器会缓存它。如果您使用 AJAX 加载它,然后 eval() 服务器发送的内容(AJAX 请求可以调整缓存),则规则略有不同。
  • 我最终比较了各种情况下的请求和响应,我唯一可以让它工作的是仅设置“Last-Modified”而不是检查“If-Modified-Since”。您的回答显然将我引向了正确的方向。谢谢。
  • 如何告诉浏览器使用缓存而不向服务器发出请求,谢谢
猜你喜欢
  • 2016-08-14
  • 1970-01-01
  • 2017-10-29
  • 2011-10-11
  • 2016-02-18
相关资源
最近更新 更多