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

Spring Boot如何根据浏览器User-Agent动态分发ES5/ES6静态资源?

Got it, let's work through this dynamic resource routing for your Spring Boot + Polymer app. You've got ES5/ES6 bundles split into /static/es5 and /static/es6, and you want to serve the right version based on the user's browser without changing the URL. Here's how to make this happen properly:


Step 1: Fix Your Static Resource Configuration

First, update your application.properties to point to the root static directory instead of hardcoding ES5. This lets Spring access both ES5 and ES6 bundles:

# Replace your old static-locations line with this
spring.resources.static-locations=classpath:/static/

This removes the hardcoded ES5 fallback and gives us flexibility to route requests dynamically.

This is the cleanest, Spring-native way to handle dynamic static resource routing—it integrates directly into Spring's resource processing chain, no extra controllers or messy forwards needed.

Create a configuration class that implements WebMvcConfigurer and defines a custom resource resolver:

import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.AbstractResourceResolver;
import org.springframework.web.servlet.resource.ResourceResolverChain;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Configuration
public class BrowserAwareResourceConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**") // Match all static resource requests
                .addResourceLocations("classpath:/static/")
                .resourceChain(true)
                .addResolver(new BrowserVersionResourceResolver());
    }

    // Inner class to handle browser-specific routing
    private static class BrowserVersionResourceResolver extends AbstractResourceResolver {
        // UA patterns for target browsers
        private static final String IE11_UA = "Trident/7.0";
        private static final String CHROME_UA = "Chrome/";
        private static final String FIREFOX_UA = "Firefox/";

        @Override
        protected Resource resolveResourceInternal(
                HttpServletRequest request,
                String requestPath,
                List<? extends Resource> locations,
                ResourceResolverChain chain
        ) {
            String userAgent = request.getHeader("User-Agent");
            String resourcePrefix = "/es5/"; // Default to ES5 for safety

            // Route based on UA
            if (userAgent != null) {
                if (userAgent.contains(CHROME_UA) || userAgent.contains(FIREFOX_UA)) {
                    resourcePrefix = "/es6/";
                } else if (userAgent.contains(IE11_UA)) {
                    resourcePrefix = "/es5/";
                }
            }

            // Rewrite the request path to use the correct ES version prefix
            String resolvedPath = resourcePrefix + requestPath;
            return new ClassPathResource(resolvedPath);
        }

        @Override
        protected String resolveUrlPathInternal(
                String resourcePath,
                List<? extends Resource> locations,
                ResourceResolverChain chain
        ) {
            // We don't need to handle URL path resolution here since we directly resolve the resource
            return null;
        }
    }
}

How This Works:

  • The resolver checks the incoming request's User-Agent header
  • Routes Chrome/Firefox requests to /es6/ resources
  • Routes IE11 requests to /es5/ resources
  • Falls back to ES5 for unknown browsers to ensure maximum compatibility
Step 3: Test the Setup
  • Use Chrome/Firefox to visit your app, open the DevTools Network tab, and verify resources load from the /es6/ directory (even though the URL shows the root path like /app.js)
  • Use IE11 to visit, and confirm resources load from /es5/
Alternative: Quick Fix with a Handler Interceptor

If you want a simpler (though less elegant) implementation, use an interceptor to forward requests to the correct directory:

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Configuration
public class BrowserRoutingInterceptorConfig implements WebMvcConfigurer {

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

    private static class BrowserRoutingInterceptor implements HandlerInterceptor {
        private static final String IE11_UA = "Trident/7.0";
        private static final String CHROME_UA = "Chrome/";
        private static final String FIREFOX_UA = "Firefox/";

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String userAgent = request.getHeader("User-Agent");
            String requestUri = request.getRequestURI();

            // Skip if already routed to ES5/ES6 to avoid infinite loops
            if (requestUri.startsWith("/es5/") || requestUri.startsWith("/es6/")) {
                return true;
            }

            String prefix = "/es5/";
            if (userAgent != null) {
                if (userAgent.contains(CHROME_UA) || userAgent.contains(FIREFOX_UA)) {
                    prefix = "/es6/";
                } else if (userAgent.contains(IE11_UA)) {
                    prefix = "/es5/";
                }
            }

            // Forward to the correct ES version directory
            request.getRequestDispatcher(prefix + requestUri.substring(1)).forward(request, response);
            return false;
        }
    }
}
Key Notes
  • UA Accuracy: IE11 uses Trident/7.0 in its UA string (not MSIE), so don't rely on outdated patterns
  • Default Fallback: Always default to ES5 for unknown browsers to avoid breaking compatibility
  • Cleanup: Make sure to remove your old spring.resources.static-locations line pointing directly to ES5

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:12:50