Как установить заголовки кэша в Spring MVC? - PullRequest
59 голосов
/ 01 сентября 2009

В контроллере Spring MVC на основе аннотаций, какой предпочтительный способ установить заголовки кэша для определенного пути?

Ответы [ 10 ]

65 голосов
/ 14 октября 2010

Я только что столкнулся с той же проблемой и нашел хорошее решение, уже предоставленное фреймворком. Класс 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>
    

После этих изменений ответы в / 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

29 голосов
/ 25 февраля 2010

Ответ довольно прост:

<code>@Controller
public class EmployeeController {<br>
    @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);
    }<br>
}
Код выше показывает именно то, что вы хотите достичь. Вы должны сделать две вещи. Добавьте «окончательный ответ HttpServletResponse» в качестве параметра. А затем установите заголовок Cache-Control на no-cache.
18 голосов
/ 01 сентября 2009

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.

15 голосов
/ 21 октября 2016

Начиная с 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

10 голосов
/ 01 сентября 2009

Вы можете использовать перехватчик обработчика и использовать предоставляемый им метод 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) 

затем просто добавьте заголовок следующим образом:

response.setHeader("Cache-Control", "no-cache");
4 голосов
/ 28 июля 2015

вы можете определить аннотацию для этого: @CacheControl(isPublic = true, maxAge = 300, sMaxAge = 300), а затем визуализировать эту аннотацию в заголовок HTTP с помощью перехватчика Spring MVC. или сделать это динамически:

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

Кстати: я только что обнаружил, что Spring MVC имеет встроенную поддержку для управления кэшем: Google WebContentInterceptor или CacheControlHandlerInterceptor или CacheControl, вы найдете его.

3 голосов
/ 06 января 2015

Я знаю, что это действительно старый, но те, кто гуглит, это может помочь:

@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);
}
1 голос
/ 15 сентября 2015

В вашем контроллере вы можете установить заголовки ответа напрямую.

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
1 голос
/ 25 февраля 2010

Вы можете расширить AnnotationMethodHandlerAdapter для поиска пользовательской аннотации элемента управления кэшем и соответственно установить заголовки http.

0 голосов
/ 04 октября 2018

Я нашел WebContentInterceptor, чтобы быть самым простым способом.

@Override
public void addInterceptors(InterceptorRegistry registry)
{
    WebContentInterceptor interceptor = new WebContentInterceptor();
    interceptor.addCacheMapping(CacheControl.noCache(), "/users", "admin");
    registry.addInterceptor(interceptor);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...