Java 你如何在 Spring MVC 中设置缓存头?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1362930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:11:04  来源:igfitidea点击:

How do you set cache headers in Spring MVC?

javaspringcachingspring-mvc

提问by D. Wroblewski

In an annotation-based Spring MVC controller, what is the preferred way to set cache headers for a specific path?

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

采纳答案by ChssPly76

org.springframework.web.servlet.support.WebContentGenerator, which is the base class for all Spring controllers has quite a few methods dealing with cache headers:

org.springframework.web.servlet.support.WebContentGenerator,它是所有 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);

They can either be invoked within your controller prior to content generation or specified as bean properties in Spring context.

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

回答by Jon

You could use a Handler Interceptor and use the postHandle method provided by it:

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

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/servlet/HandlerInterceptor.html

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/servlet/HandlerInterceptor.html

postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 

then just add a header as follows in the method:

然后只需在方法中添加如下标题:

response.setHeader("Cache-Control", "no-cache");

回答by goroncy

The answer is quite simple:

答案很简单:

@Controller
public class EmployeeController {
@RequestMapping(value = "/find/employer/{employerId}", method = RequestMethod.GET) public List getEmployees(@PathVariable("employerId") Long employerId, final HttpServletResponse response) { response.setHeader("Cache-Control", "no-cache"); return employeeService.findEmployeesForEmployer(employerId); }
}
上面的代码准确地显示了您想要实现的目标。你必须做两件事。添加“最终 HttpServletResponse 响应”作为您的参数。然后将标头 Cache-Control 设置为 no-cache。

回答by goroncy

You could extend AnnotationMethodHandlerAdapter to look for a custom cache control annotation and set the http headers accordingly.

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

回答by Eric R. Rath

I just encountered the same problem, and found a good solution already provided by the framework. The org.springframework.web.servlet.mvc.WebContentInterceptorclass allows you to define default caching behaviour, plus path-specific overrides (with the same path-matcher behaviour used elsewhere). The steps for me were:

我刚遇到同样的问题,找到了框架已经提供的很好的解决方案。该org.springframework.web.servlet.mvc.WebContentInterceptor级允许你定义默认缓存行为,加上路径特定的覆盖(具有相同的路径匹配行为别处使用)。我的步骤是:

  1. Ensure my instance of org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterdoes not have the "cacheSeconds" property set.
  2. Add an instance of WebContentInterceptor:

    <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>
    
  1. 确保我的实例org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter没有设置“cacheSeconds”属性。
  2. 添加一个实例WebContentInterceptor

    <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>
    

After these changes, responses under /foo included headers to discourage caching, responses under /cache/me included headers to encourage caching, and responses under /cache/agnostic included no cache-related headers.

在这些更改之后,/foo 下的响应包含标题以阻止缓存,/cache/me 下的响应包含标题以鼓励缓存,而 /cache/agnostic 下的响应不包含与缓存相关的标题。



If using a pure Java configuration:

如果使用纯 Java 配置:

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  /* Time, in seconds, to have the browser cache static resources (one week). */
  private static final int BROWSER_CACHE_CONTROL = 604800;

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry
     .addResourceHandler("/images/**")
     .addResourceLocations("/images/")
     .setCachePeriod(BROWSER_CACHE_CONTROL);
  }
}

See also: http://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html

另见:http: //docs.spring.io/spring-security/site/docs/current/reference/html/headers.html

回答by realcnbs

I know this is a really old one, but those who are googling, this might help:

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

@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);
}

回答by arganzheng

you can define a anotation for this: @CacheControl(isPublic = true, maxAge = 300, sMaxAge = 300), then render this anotation to HTTP Header with Spring MVC interceptor. or do it dynamic:

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

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);
}

Implication can be found here: 优雅的Builder模式

含义可以在这里找到:优雅的Builder模式

BTW: I just found that Spring MVC has build-in support for cache control: Google WebContentInterceptor or CacheControlHandlerInterceptor or CacheControl, you will find it.

顺便说一句:我刚刚发现 Spring MVC 内置了对缓存控制的支持:Google WebContentInterceptor 或 CacheControlHandlerInterceptor 或 CacheControl,你会找到的。

回答by hakunami

In your controller, you can set response headers directly.

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

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);

回答by Gian Marco Gherardi

Starting with Spring 4.2you can do this:

Spring 4.2开始,您可以这样做:

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);
    }
}

CacheControlobject is a builder with many configuration options, see JavaDoc

CacheControlobject 是一个具有许多配置选项的构建器,请参阅JavaDoc

回答by Liang Zhou

I found WebContentInterceptorto be the easiest way to go.

我发现WebContentInterceptor这是最简单的方法。

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