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

如何基于Java Spring MVC实现Web服务数据的浏览器端缓存?

Alright, let's figure out how to implement browser caching for your Spring MVC-powered web project—this will cut down on redundant API calls, reduce those unnecessary read operations, and speed up page loads. Here's a step-by-step breakdown covering both backend configuration and frontend best practices:

Implementing Browser Caching for Spring MVC API Responses

1. Configure Cache Headers on the Spring MVC Backend

Browsers only cache responses when the server explicitly tells them to via HTTP headers. We'll set up these headers to control how long the browser keeps the data and when it needs to revalidate.

Option 1: Global Cache Configuration (For All APIs)

Use an interceptor to apply cache rules across all your API endpoints at once:

@Configuration
public class WebCacheConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CacheControlInterceptor());
    }

    private static class CacheControlInterceptor implements HandlerInterceptor {
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            // Target only your API paths (adjust the URI pattern to match yours)
            if (request.getRequestURI().startsWith("/api/")) {
                // Allow public caching (including browser) for 1 hour (3600 seconds)
                response.setHeader("Cache-Control", "public, max-age=3600");
                // Optional: Add an ETag for conditional requests (when cache expires)
                String responseBody = response.getContentAsString();
                response.setHeader("ETag", generateETag(responseBody));
            }
        }

        private String generateETag(String content) {
            // Simple ETag generation using MD5 hash of the response content
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] digest = md.digest(content.getBytes(StandardCharsets.UTF_8));
                return Base64.getEncoder().encodeToString(digest);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("Failed to generate ETag", e);
            }
        }
    }
}
  • Cache-Control: public, max-age=3600: Tells browsers they can cache this response for 1 hour. During this time, they won't hit your API at all.
  • ETag: A unique identifier for the response content. When the cache expires, the browser sends this ETag to the server—if the content hasn't changed, the server returns a 304 Not Modified status, and the browser reuses its cache.

Option 2: Per-API Cache Configuration (Flexible for Specific Endpoints)

If some APIs need different cache rules, set headers directly in your controller methods:

@GetMapping("/api/user/profile")
public ResponseEntity<UserProfile> getUserProfile() {
    UserProfile profile = userService.fetchUserProfile();
    return ResponseEntity.ok()
            // Cache user-specific data for 30 minutes (private = not shared with CDNs/proxies)
            .header("Cache-Control", "private, max-age=1800")
            .header("ETag", generateETag(profile))
            .body(profile);
}

2. Frontend (Browser) Setup

Most modern browsers will automatically respect the cache headers you set, but there are a few things to avoid breaking this behavior:

Using Fetch API

Fetch honors browser caching by default for GET requests. You can add optional logging to confirm cache hits:

fetch('/api/data')
  .then(response => {
    if (response.status === 304) {
      console.log('Reusing cached data (server confirmed no changes)');
    }
    return response.json();
  })
  .then(data => {
    // Render your page with the cached or fresh data
    renderPage(data);
  });

Don't add Cache-Control: no-cache or Pragma: no-cache to your request headers—this will force the browser to skip caching entirely.

Using Axios

Axios also respects browser caching out of the box. Just make sure you haven't disabled it in your global config:

axios.get('/api/data')
  .then(response => {
    if (response.status === 304) {
      console.log('Cached data hit!');
    }
    processData(response.data);
  });

If you previously set axios.defaults.headers.common['Cache-Control'] = 'no-cache', remove that line or override it for specific requests.

3. Verify the Cache is Working

Use your browser's DevTools (Network tab) to confirm:

  • First request: Status code 200, Size shows the full response size, and Response Headers include Cache-Control and ETag.
  • Second request (within max-age): Status code 200 (from disk cache) or 200 (from memory cache)—no request is sent to your server.
  • After cache expires: Status code 304, server sends no response body, and the browser reuses its cached data.

4. Handle Edge Cases

  • Dynamic Data Updates: If you need to force a fresh update before the cache expires, add a version parameter to your API URL (e.g., /api/data?v=2)—this counts as a new request, so the browser will fetch fresh data.
  • Sensitive Data: For user-specific data, use Cache-Control: private instead of public—this ensures the cache is only stored in the user's browser, not shared with CDNs or proxies.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:12:16