You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中为多个RestController端点统一配置Cache-Control

统一为Spring 5 REST接口设置Cache-Control的解决方案

嘿,我明白你现在的困扰——每个@RestController方法都要手动用ResponseEntity设置Cache-Control,代码重复得让人头疼!别担心,Spring 5里有好几种方式能帮你统一配置,彻底告别冗余代码。

方案一:使用HandlerInterceptor全局拦截

拦截器可以在请求处理完成后统一给响应添加Cache-Control头,适合全局范围内的所有接口(或者你指定的路径)。

第一步:编写拦截器类

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;

public class CacheControlInterceptor implements HandlerInterceptor {
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 这里可以根据请求路径、处理器类型做精准判断,比如只给@RestController的接口加头
        // 设置你需要的Cache-Control策略,比如禁止缓存
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        // 兼容旧浏览器的额外头
        response.setHeader("Expires", "0");
        response.setHeader("Pragma", "no-cache");
    }
}

第二步:注册拦截器到Spring配置

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 指定只拦截你的API路径,比如/api/**
        registry.addInterceptor(new CacheControlInterceptor())
                .addPathPatterns("/api/**");
    }
}

方案二:使用@ControllerAdvice + ResponseBodyAdvice

这个方案更精准地针对@RestController(或@ResponseBody)的响应,能在返回体写入前修改响应头,非常适合REST接口场景。

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

// 指定你的API所在的包,只处理该包下的接口
@ControllerAdvice(basePackages = "com.yourproject.api")
public class GlobalCacheControlAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<?> converterType) {
        // 返回true表示处理所有@ResponseBody的方法,也可以根据返回类型、注解做筛选
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<?> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 设置Cache-Control头
        response.getHeaders().setCacheControl("no-cache, no-store, must-revalidate");
        response.getHeaders().setExpires(0);
        response.getHeaders().setPragma("no-cache");
        return body;
    }
}

灵活覆盖全局配置

如果某个接口需要单独设置不同的Cache-Control策略,你依然可以用原来的ResponseEntity方式——ResponseEntity的头会覆盖全局配置的头,完全不影响灵活性。

比如:

@PostMapping("/search")
public ResponseEntity<SearchResultDto> search(SearchDto searchDto) {
    // ...业务逻辑
    return ResponseEntity.ok()
            .cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES))
            .body(searchResult);
}

这样这个接口就会使用max-age=600的缓存策略,而不是全局的禁止缓存。

内容的提问来源于stack exchange,提问作者mangei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:56:09