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

Spring项目中基于Polymer push-manifest.json实现HTTP2服务器推送的示例咨询

Implementing HTTP/2 Server Push with Polymer's push-manifest.json in Spring Projects

Hey there! Combining Polymer's push-manifest.json with HTTP/2 Server Push in Spring is totally doable, and there are solid patterns to make it work smoothly. Let's walk through how to set this up, with practical code snippets and real-world considerations.

First: Understanding Your push-manifest.json

Your example manifest gives clear instructions to the server: "When a client requests theme/test-theme/index.html, immediately push theme/test-theme/somestyling.css over the same HTTP/2 connection". The type: "document" and weight: 1 hints help the server prioritize this push (weight 1 is the highest priority for critical resources).

{ 
  "theme/test-theme/index.html": { 
    "theme/test-theme/somestyling.css": { 
      "type": "document", 
      "weight": 1 
    } 
  } 
}

Step 1: Ensure Your Spring Setup Supports HTTP/2

First, make sure your server (Tomcat 9+, Jetty 10+, or Undertow 2.x+) is configured for HTTP/2. For a Spring Boot app, you can enable this in application.properties:

# For Tomcat (adjust for other servers as needed)
server.http2.enabled=true
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=your-secure-password
server.ssl.key-store-type=PKCS12

Note: HTTP/2 requires HTTPS in production (most browsers enforce this), though you can test with HTTP locally in some servers for development.

Step 2: Load the push-manifest.json into Spring

Create a configuration bean to load and parse the manifest once at startup—this avoids reading the file on every request:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.util.Map;

@Configuration
public class PushManifestConfig {

    @Bean
    public Map<String, Map<String, PushResourceMetadata>> pushManifest(ObjectMapper objectMapper) throws IOException {
        ClassPathResource manifestResource = new ClassPathResource("push-manifest.json");
        return objectMapper.readValue(manifestResource.getInputStream(), 
            new com.fasterxml.jackson.core.type.TypeReference<>() {});
    }

    // Helper record to map the metadata fields from the manifest
    public record PushResourceMetadata(String type, int weight) {}
}

Step 3: Implement Server Push with a Request Interceptor

Use a HandlerInterceptor to intercept requests that match entries in our manifest and trigger the push before the response is sent. This keeps the logic centralized:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Component
public class Http2PushInterceptor implements HandlerInterceptor {

    private final Map<String, Map<String, PushManifestConfig.PushResourceMetadata>> pushManifest;

    public Http2PushInterceptor(Map<String, Map<String, PushManifestConfig.PushResourceMetadata>> pushManifest) {
        this.pushManifest = pushManifest;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // Get the request path (adjust if your app uses a context path)
        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
        
        // Check if this path has associated resources to push
        Map<String, PushManifestConfig.PushResourceMetadata> resourcesToPush = pushManifest.get(requestPath);
        if (resourcesToPush != null && response instanceof org.springframework.http.server.ServletServerHttpResponse servletResponse) {
            org.springframework.http.server.ServerHttpResponse springResponse = servletResponse.getServerHttpResponse();
            
            for (String resourcePath : resourcesToPush.keySet()) {
                // Trigger the HTTP/2 push for each resource
                springResponse.pushBuilder()
                        .path(resourcePath)
                        .push();
            }
        }
    }
}

Don't forget to register the interceptor in your Spring web configuration:

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 WebConfig implements WebMvcConfigurer {

    private final Http2PushInterceptor http2PushInterceptor;

    public WebConfig(Http2PushInterceptor http2PushInterceptor) {
        this.http2PushInterceptor = http2PushInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(http2PushInterceptor);
    }
}

Step 4: Production-Ready Enhancements

To make this implementation mature, add these key touches:

  • Cache Validation: Check if the client already has the resource cached (using If-None-Match or If-Modified-Since headers) before pushing. Use Spring's ResourceHttpRequestHandler to fetch resource metadata and compare headers.
  • Priority Ordering: Use the weight field from the manifest to order pushes (higher weight first) for critical resources.
  • Static Resource Alignment: Ensure pushed paths match your Spring static resource mappings (e.g., if your CSS lives in /static/theme/, adjust the path to map correctly to /theme/).
  • Fallback Logic: Gracefully handle cases where the server doesn't support HTTP/2 or the resource doesn't exist.

Real-World Implementation Patterns

Many Spring Boot teams use this pattern alongside Polymer or other frontend frameworks:

  • Combine it with Thymeleaf/JSP views, where the interceptor triggers pushes when the view's URL matches the manifest.
  • Extend the interceptor to handle wildcard paths in the manifest using Spring's AntPathMatcher for more flexible matching.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:20:19