强制浏览器缓存Spring MVC的JS响应

时间:2012-07-25 09:38:44

标签: java json spring spring-mvc

每当我需要在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文件。

由于此文件是会话依赖的,我无法生成它并将其视为静态文件。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

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

在通常情况下,您可以使用时间戳来确定文件是否已更改。但是,因为它永远不会改变你的情况,你可以回复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