How do you set cache headers in Spring MVC?

后端 未结 10 1048
名媛妹妹
名媛妹妹 2020-12-04 09:23

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

相关标签:
10条回答
  • 2020-12-04 09:41

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

    0 讨论(0)
  • 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);
    }
    
    0 讨论(0)
  • 2020-12-04 09:48

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

    1. Ensure my instance of org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter does 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>
      

    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.


    If using a pure Java configuration:

    @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

    0 讨论(0)
  • 2020-12-04 09:49

    Starting with Spring 4.2 you can do this:

    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 object is a builder with many configuration options, see JavaDoc

    0 讨论(0)
  • 2020-12-04 09:49

    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:

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

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

    0 讨论(0)
  • 2020-12-04 09:51

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

    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");
    
    0 讨论(0)
提交回复
热议问题