0

我希望我对 Spring MVC 控制器的响应被视为浏览器中的静态内容。只需获取一次,然后从浏览器缓存中获取它以获取304 Not Modified状态代码。我有简单的方法的普通 Spring MVC 控制器。simpleService.getVariables()正在从数据库中获取大量内容。它返回字符串。

@RequestMapping(value = "/jsContent.htm")
public ModelAndView jsContent(@RequestParam("ver") String version, 
        HttpServletRequest request, HttpServletResponse response) {
    ModelAndView mav = new ModelAndView("jsContent");
    mav.addObject("variables", simpleService.getVariables());
    return mav;
}

响应由 Apache Tiles 处理。是普通的firstPartJavaScript 文件,secondPartString添加到ModelAndView对象中的。

<definition name="javascript" template="/WEB-INF/tiles/javascript.jsp" />
<definition name="jsContent" extends="javascript">
    <put-attribute name="firstPart" expression="/js/content/static.js" />
    <put-attribute name="secondPart" expression="${variables}" />
</definition>

为了expressions在瓷砖中启用,我添加了这个tilesProperties

这是我的tiles/javascript.jsp

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insertAttribute name="firstPart" />
<tiles:insertAttribute name="secondPart" />

我只是通过304 Not Modified将此 Spring 过滤器添加到web.xml. 然而,内容仍然每次都在获取,并且通过Etag标题比较,状态码是304有任何变化的时候。

<filter>
    <filter-name>etagFilter</filter-name>
    <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>etagFilter</filter-name>
    <servlet-name>dispatcher</servlet-name>
</filter-mapping>

如何获取 Spring Controller 的缓存响应?我试图通过 HTTP Headers 来实现这一点,但它不起作用。

4

1 回答 1

1

ETag 方法在这里不适合您的需要。过滤器的工作方式是每次收到请求时调用控制器,然后计算响应的哈希值,将哈希值(ETag)与请求中发送的 Etag 进行比较,如果它们匹配,则过滤器假定数据没有改变,并发送没有响应正文的客户端 304。

可以看到,这种方法并没有减少你的实际控制器需要为一个请求做的工作量,它只是提高了带宽利用率,并为客户端提供了更快的响应(由于不是发送响应体,我们只是发送一个状态码)。

因此,对于您的情况,您应该使用Last-Modified响应标头和If-Modified-Since请求标头。要使用 Spring MVC 做到这一点,您可以尝试以下方法: 1. 在您的控制器中,维护一个以毫秒为单位的时间戳,它应该与资源的最后修改时间相同。我将其设置为部署时间,并假设我的内容在应用程序运行时不会被修改。如果您想强制浏览器加载新副本,即使它们有旧版本,您也可以选择根据需要进行更新。

  1. 接受 org.springframework.web.context.request.WebRequest 作为控制器方法的参数。

  2. 在你的方法中,做实际的处理,只有当webRequest.checkNotModified(lastModifiedTime)是假的。

示例代码:

public class MyController {
//Injected 
private long lastModifiedTime;

public void getFullSdk(WebRequest webRequest, HttpServletRequest request, 
                HttpServletResponse response) throws Exception {

    if (webRequest.checkNotModified(lastModifiedTime)) {
        return;
    } else {
        // real expensive code goes here
        // write to response
    }
}
}

希望这可以帮助。

于 2013-04-19T12:39:26.650 回答