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

D. *_*ski 60 java spring caching spring-mvc

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

Eri*_*ath 66

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

  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>
    
    Run Code Online (Sandbox Code Playgroud)

在这些更改之后,/ foo下的响应包括阻止缓存的标头,/ cache/me下的响应包括鼓励缓存的标头,以及/ cache/agnostic下的响应包括没有缓存相关的标头.


如果使用纯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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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


gor*_*ncy 30

答案很简单:

@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); }
}
上面的代码显示了您想要实现的目标.你必须做两件事.添加"final HttpServletResponse response"作为参数.然后将标头Cache-Control设置为no-cache.

  • 这必须添加到每个请求.不是一个很好的解决方案,可以将标题添加到所有请求中. (10认同)

Chs*_*y76 19

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);
Run Code Online (Sandbox Code Playgroud)

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

  • 因为我的问题涉及如何使用基于注释的控制器执行此操作.您的解决方案仅适用于继承WebContentGenerator的控制器.不是吗? (6认同)
  • 如果您想根据**特定路径**更改缓存设置,那么扩展`AbstractController`是迄今为止最简单的解决方案.如果要将缓存设置应用于所有控制器,可以在Spring上下文中的"AnnotationMethodHandlerAdapter"实例上为基于注释的控制器指定它们.这是一个例子:http://static.springsource.org/spring/docs/2.5.6/reference/mvc.html#mvc-ann-initbinder(忽略init绑定器,你不需要它) (4认同)
  • 但是,正如我在我的问题中所写,我使用的是基于注释的控制器,它不是任何spring基类的子类.这对我有什么帮助? (3认同)

Gia*_*rdi 16

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Jon*_*Jon 10

您可以使用Handler Interceptor并使用它提供的postHandle方法:

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) 
Run Code Online (Sandbox Code Playgroud)

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

response.setHeader("Cache-Control", "no-cache");
Run Code Online (Sandbox Code Playgroud)


Lia*_*hou 5

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

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