В контроллере MVC на основе аннотаций Spring, каков предпочтительный способ установки заголовков кеша для определенного пути?
Как установить заголовки кеша в Spring MVC?
Ответ 1
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);
Они могут быть вызваны внутри вашего контроллера до создания контента или указаны как bean свойства в контексте Spring.
Ответ 2
Я только столкнулся с той же проблемой и нашел хорошее решение, уже предоставленное каркасом. Класс org.springframework.web.servlet.mvc.WebContentInterceptor
позволяет вам определить поведение кэширования по умолчанию, а также переопределения для каждого пути (с тем же поведением, что и в других местах). Для меня были следующие шаги:
- Убедитесь, что мой экземпляр
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 включали заголовки, чтобы препятствовать кешированию, ответы в /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);
}
}
Смотрите также: http://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html
Ответ 3
Ответ довольно прост:
@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);
}
}
Code above shows exactly what you want to achive. You have to do two things. Add "final HttpServletResponse response" as your parameter. And then set header Cache-Control to no-cache. Ответ 4
Вы можете использовать Interceptor Handler и использовать метод postHandle, предоставляемый им:
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
то просто добавьте заголовок следующим образом в методе:
response.setHeader("Cache-Control", "no-cache");
Ответ 5
Начиная с 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
объект - это построитель со многими параметрами конфигурации, см. JavaDoc
Ответ 6
вы можете определить для этого анотацию: @CacheControl(isPublic = true, maxAge = 300, sMaxAge = 300)
, затем отнести эту анотацию к заголовку HTTP с помощью перехватчика MVC Spring. или сделать это динамическим:
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);
}
Последствия можно найти здесь: 优雅 的 Builder 模式
BTW: Я просто обнаружил, что Spring MVC имеет встроенную поддержку управления кешем: Google WebContentInterceptor или CacheControlHandlerInterceptor или CacheControl, вы найдете его.
Ответ 7
Я знаю, что это действительно старый, но те, кто занимается поиском в Интернете, могут помочь:
@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);
}
Ответ 8
Вы можете расширить AnnotationMethodHandlerAdapter, чтобы искать пользовательскую аннотацию управления кешем и соответственно настроить заголовки http.
Ответ 9
В вашем контроллере вы можете напрямую настроить заголовки ответов.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);