Java 如何在SpringMVC中设置缓存头?

Java 如何在SpringMVC中设置缓存头?,java,spring,caching,spring-mvc,Java,Spring,Caching,Spring Mvc,在基于注释的Spring MVC控制器中,为特定路径设置缓存头的首选方法是什么?您可以使用处理程序拦截器并使用它提供的postHandle方法: 然后只需在方法中添加一个标题,如下所示: response.setHeader("Cache-Control", "no-cache"); ,它是所有Spring控制器的基类,有许多处理缓存头的方法: /* Set whether to use the HTTP 1.1 cache-control header. Default is "true"

在基于注释的Spring MVC控制器中,为特定路径设置缓存头的首选方法是什么?

您可以使用处理程序拦截器并使用它提供的postHandle方法:

然后只需在方法中添加一个标题,如下所示:

response.setHeader("Cache-Control", "no-cache");
,它是所有Spring控制器的基类,有许多处理缓存头的方法:

/* Set whether to use the HTTP 1.1 cache-control header. Default is "true".
 * <p>Note: Cache headers will only get applied if caching is enabled
 * (or explicitly prevented) for the current request. */
public final void setUseCacheControlHeader();

/* Return whether the HTTP 1.1 cache-control header is used. */
public final boolean isUseCacheControlHeader();

/* Set whether to use the HTTP 1.1 cache-control header value "no-store"
 * when preventing caching. Default is "true". */
public final void setUseCacheControlNoStore(boolean useCacheControlNoStore);

/* Cache content for the given number of seconds. Default is -1,
 * indicating no generation of cache-related headers.
 * Only if this is set to 0 (no cache) or a positive value (cache for
 * this many seconds) will this class generate cache headers.
 * The headers can be overwritten by subclasses, before content is generated. */
public final void setCacheSeconds(int seconds);
/*设置是否使用HTTP 1.1缓存控制头。默认值为“true”。
*注意:只有启用缓存时才会应用缓存头
*(或明确禁止)用于当前请求*/
公共最终作废setUseCacheControlHeader();
/*返回是否使用HTTP 1.1缓存控制头*/
公共最终布尔值isUseCacheControlHeader();
/*设置是否使用HTTP 1.1缓存控制头值“no store”
*当阻止缓存时。默认值为“true”*/
公共最终无效集合useCacheControlNoStore(布尔值useCacheControlNoStore);
/*缓存给定秒数的内容。默认值为-1,
*指示未生成与缓存相关的标头。
*仅当该值设置为0(无缓存)或正值(缓存为
*这个类将生成缓存头。
*在生成内容之前,标题可以被子类覆盖*/
公共最终无效设置缓存秒数(整数秒);

它们可以在生成内容之前在控制器中调用,也可以在Spring上下文中指定为bean属性。

答案很简单:

@控制器
公共类EmployeeController{
@RequestMapping(value=“/find/employer/{employerId}”,method=RequestMethod.GET) 公共列表getEmployees(@PathVariable(“EmployeerId”)长EmployeerId,最终HttpServletResponse){ setHeader(“缓存控制”、“无缓存”); 返回employeeService.findEmployeesForEmployer(EmployeerID); }
}

上面的代码正好显示了您想要实现的目标。你必须做两件事。添加“final HttpServletResponse”作为参数。然后将标头缓存控制设置为无缓存

您可以扩展AnnotationMethodHandlerAdapter以查找自定义缓存控件注释,并相应地设置http头。

我刚刚遇到了同样的问题,并找到了框架已经提供的一个很好的解决方案。
org.springframework.web.servlet.mvc.WebContentInterceptor
类允许您定义默认缓存行为,以及特定于路径的重写(与其他地方使用的路径匹配器行为相同)。我的步骤是:

  • 确保我的
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
    实例未设置“cacheSeconds”属性
  • 添加
    WebContent Interceptor的实例

    <mvc:interceptors>
    ...
    <bean class="org.springframework.web.servlet.mvc.WebContentInterceptor" p:cacheSeconds="0" p:alwaysUseFullPath="true" >
        <property name="cacheMappings">
            <props>
                <!-- cache for one month -->
                <prop key="/cache/me/**">2592000</prop>
                <!-- don't set cache headers -->
                <prop key="/cache/agnostic/**">-1</prop>
            </props>
        </property>
    </bean>
    ...
    </mvc:interceptors>
    

    另请参见:

    我知道这是一个非常古老的版本,但对于那些使用谷歌搜索的人来说,这可能会有所帮助:

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
    
        WebContentInterceptor interceptor = new WebContentInterceptor();
    
        Properties mappings = new Properties();
        mappings.put("/", "2592000");
        mappings.put("/admin", "-1");
        interceptor.setCacheMappings(mappings);
    
        registry.addInterceptor(interceptor);
    }
    

    您可以为此定义一个地址:
    @CacheControl(isPublic=true,maxAge=300,sMaxAge=300)
    ,然后使用Spring MVC拦截器将此地址呈现到HTTP标头。或者做动态的:

    int age = calculateLeftTiming();
    String cacheControlValue = CacheControlHeader.newBuilder()
          .setCacheType(CacheType.PUBLIC)
          .setMaxAge(age)
          .setsMaxAge(age).build().stringValue();
    if (StringUtils.isNotBlank(cacheControlValue)) {
        response.addHeader("Cache-Control", cacheControlValue);
    }
    
    其含义如下:

    顺便说一句:我刚刚发现Spring MVC内置了对缓存控制的支持:
    Google WebContent Interceptor或CacheControlHandlerInterceptor或CacheControl,您将找到它。

    在您的控制器中,您可以直接设置响应标题

    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);
    
    首先,您可以执行以下操作:

    import org.springframework.http.CacheControl;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.TimeUnit;
    
    @RestController
    public class CachingController {
        @RequestMapping(method = RequestMethod.GET, path = "/cachedapi")
        public ResponseEntity<MyDto> getPermissions() {
    
            MyDto body = new MyDto();
    
            return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
                .body(body);
        }
    }
    
    import org.springframework.http.CacheControl;
    导入org.springframework.http.MediaType;
    导入org.springframework.http.ResponseEntity;
    导入org.springframework.web.bind.annotation.RequestMapping;
    导入org.springframework.web.bind.annotation.RequestMethod;
    导入org.springframework.web.bind.annotation.RestController;
    导入java.util.concurrent.TimeUnit;
    @RestController
    公共类CachingController{
    @RequestMapping(method=RequestMethod.GET,path=“/cachedapi”)
    公共响应权限getPermissions(){
    MyDto body=新的MyDto();
    返回ResponseEntity.ok()
    .cacheControl(cacheControl.maxAge(20,时间单位.秒))
    .机构(机构);
    }
    }
    

    CacheControl
    对象是一个具有许多配置选项的构建器,请参见我发现
    WebContentInterceptor
    是最简单的方法

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        WebContentInterceptor interceptor = new WebContentInterceptor();
        interceptor.addCacheMapping(CacheControl.noCache(), "/users", "admin");
        registry.addInterceptor(interceptor);
    }
    

    但是,正如我在问题中所写的,我使用的是一个基于注释的控制器,它不从任何spring基类派生子类。这对我有什么帮助?如果您想根据特定路径更改缓存设置,扩展
    AbstractController
    是迄今为止最简单的解决方案。如果要将缓存设置应用于所有控制器,可以在基于注释的控制器的Spring上下文中的
    AnnotationMethodHandlerAdapter
    实例上指定它们。下面是一个示例:(忽略init绑定器,您不需要它),因为我的问题涉及如何使用基于注释的控制器来实现这一点。您的解决方案仅适用于子类WebContentGenerator的控制器。不是吗?我在上面的评论中已经提到了这一点。如果你认为你能找到更好的解决办法,我祝你好运。这就是为什么我对你的评论投了赞成票。你为什么不改为编辑你的答案?这将不得不添加到每个请求中。这不是一个很好的解决方案,无法将标题添加到所有请求中。@JesseJ哪部分不起作用?我试过了,它对我很有效。@yincrash,引用OP:what是为特定路径设置缓存头的首选方法,我试过将其用于存储在数据库中的图像。我可以很容易地找回它们。它们出现了,但是FireBug总是告诉我状态“200OK”,所以没有缓存。有什么想法吗?这行不通,因为我没有mvc或p的前缀。它们应该是什么?Jesse-检查上下文定义文件的根元素;您应该有一个名称空间元素,如“xmlns:mvc=”“”,以及另一个名为“xsi:schemaLocation”的属性,其值包括“”。参见示例o
    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);
    
    import org.springframework.http.CacheControl;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.TimeUnit;
    
    @RestController
    public class CachingController {
        @RequestMapping(method = RequestMethod.GET, path = "/cachedapi")
        public ResponseEntity<MyDto> getPermissions() {
    
            MyDto body = new MyDto();
    
            return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
                .body(body);
        }
    }
    
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        WebContentInterceptor interceptor = new WebContentInterceptor();
        interceptor.addCacheMapping(CacheControl.noCache(), "/users", "admin");
        registry.addInterceptor(interceptor);
    }