添加@RefreshScope导致跨域FilterRegistrationBean失效求助
问题:添加@RefreshScope后跨域配置失效且无法实时刷新
原本正常的跨域配置,为实现配置实时刷新给配置类添加@RefreshScope注解后,不仅无法触发配置刷新,还导致跨域完全失效。前端访问接口时出现以下错误:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
初始有效跨域配置代码
@Slf4j @Configuration public class FilterConfiguration { @Value("${jlpay.business.filter.allowCredentials:true}") private boolean allowCredentials; @Value("${jlpay.business.filter.allowedHeader:*}") private String allowedHeader; @Value("${jlpay.business.filter.allowedMethod:*}") private String allowedMethod; @Value("${jlpay.business.filter.allowedOrigin:*}") private String allowedOrigin; @Value("${jlpay.business.filter.corsPath:/**}") private String corsPath; /** * 跨域请求配置 * @return */ private CorsConfiguration buildCorsConfig() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowCredentials(allowCredentials); corsConfig.addAllowedHeader(allowedHeader); corsConfig.addAllowedMethod(allowedMethod); //指定域名拦截配置 if (!StringUtils.isEmpty(allowedOrigin) && !CorsConfiguration.ALL.equals(allowedOrigin)) { String[] originArr = allowedOrigin.split(","); for (String origin : originArr) { corsConfig.addAllowedOrigin(origin); } } else { corsConfig.addAllowedOrigin(CorsConfiguration.ALL); } return corsConfig; } /** * 跨域请求过滤器配置 */ @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); //注:暂定所有接口均允许跨域,建议针对具体接口配置允许跨域 configSource.registerCorsConfiguration(corsPath, buildCorsConfig()); log.info("跨域请求过滤器配置:{}", JSONObject.toJSONString(configSource.getCorsConfigurations())); return new CorsFilter(configSource); } /** * 跨域请求配置注册至过滤器 * @return */ @Bean public FilterRegistrationBean corsFilterRegist() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(corsFilter()); filterRegistration.setName("corsFilter"); filterRegistration.setOrder(0); return filterRegistration; } }
添加@RefreshScope后的配置代码
@Slf4j @Configuration @RefreshScope public class FilterConfiguration { @Value("${jlpay.business.filter.allowCredentials:true}") private boolean allowCredentials; @Value("${jlpay.business.filter.allowedHeader:*}") private String allowedHeader; @Value("${jlpay.business.filter.allowedMethod:*}") private String allowedMethod; @Value("${jlpay.business.filter.allowedOrigin:*}") private String allowedOrigin; @Value("${jlpay.business.filter.corsPath:/**}") private String corsPath; /** * 跨域请求配置 * @return */ private CorsConfiguration buildCorsConfig() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowCredentials(allowCredentials); corsConfig.addAllowedHeader(allowedHeader); corsConfig.addAllowedMethod(allowedMethod); //指定域名拦截配置 if (!StringUtils.isEmpty(allowedOrigin) && !CorsConfiguration.ALL.equals(allowedOrigin)) { String[] originArr = allowedOrigin.split(","); for (String origin : originArr) { corsConfig.addAllowedOrigin(origin); } } else { corsConfig.addAllowedOrigin(CorsConfiguration.ALL); } return corsConfig; } /** * 跨域请求过滤器配置 */ @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); //注:暂定所有接口均允许跨域,建议针对具体接口配置允许跨域 configSource.registerCorsConfiguration(corsPath, buildCorsConfig()); log.info("跨域请求过滤器配置:{}", JSONObject.toJSONString(configSource.getCorsConfigurations())); return new CorsFilter(configSource); } /** * 跨域请求配置注册至过滤器 * @return */ @Bean @RefreshScope public FilterRegistrationBean corsFilterRegist() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(corsFilter()); filterRegistration.setName("corsFilter"); filterRegistration.setOrder(0); return filterRegistration; } }
问题原因
- @RefreshScope作用于Configuration类的冲突:将
@RefreshScope直接加在@Configuration类上,会导致该类生成的所有Bean都被代理,而过滤器的注册逻辑依赖容器的Bean生命周期,代理后的Bean无法被正确识别为过滤器,导致跨域配置不生效。 - 重复@RefreshScope导致实例不一致:在
FilterRegistrationBean的@Bean方法上重复添加@RefreshScope,会导致过滤器实例和配置实例分离,刷新时无法同步更新过滤器链中的实例。
解决方案
步骤1:抽离配置属性类
将跨域相关配置抽成独立类,用@ConfigurationProperties绑定配置前缀,仅给这个类加@RefreshScope实现属性实时刷新。
@Data @ConfigurationProperties(prefix = "jlpay.business.filter") @RefreshScope public class CorsProperties { private boolean allowCredentials = true; private String allowedHeader = "*"; private String allowedMethod = "*"; private String allowedOrigin = "*"; private String corsPath = "/**"; }
步骤2:修改FilterConfiguration
去掉Configuration类上的@RefreshScope,通过构造注入CorsProperties,并给CorsFilter的@Bean方法加@RefreshScope确保配置变化时重建过滤器。
@Slf4j @Configuration @EnableConfigurationProperties(CorsProperties.class) public class FilterConfiguration { private final CorsProperties corsProperties; public FilterConfiguration(CorsProperties corsProperties) { this.corsProperties = corsProperties; } private CorsConfiguration buildCorsConfig() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowCredentials(corsProperties.isAllowCredentials()); corsConfig.addAllowedHeader(corsProperties.getAllowedHeader()); corsConfig.addAllowedMethod(corsProperties.getAllowedMethod()); String allowedOrigin = corsProperties.getAllowedOrigin(); if (!StringUtils.isEmpty(allowedOrigin) && !CorsConfiguration.ALL.equals(allowedOrigin)) { String[] originArr = allowedOrigin.split(","); for (String origin : originArr) { corsConfig.addAllowedOrigin(origin); } } else { corsConfig.addAllowedOrigin(CorsConfiguration.ALL); } return corsConfig; } @Bean @RefreshScope public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration(corsProperties.getCorsPath(), buildCorsConfig()); log.info("跨域请求过滤器配置:{}", JSONObject.toJSONString(configSource.getCorsConfigurations())); return new CorsFilter(configSource); } @Bean public FilterRegistrationBean corsFilterRegist() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(corsFilter()); filterRegistration.setName("corsFilter"); filterRegistration.setOrder(0); return filterRegistration; } }
步骤3:验证配置刷新
- 确保项目已引入Spring Cloud Config相关依赖(若使用自动刷新机制)。
- 配置
/actuator/refresh端点(需开启Actuator),修改配置后通过POST请求触发刷新。 - 查看日志确认配置已更新,再测试前端跨域请求是否恢复正常。
内容的提问来源于stack exchange,提问作者tao zheng
相关产品推荐
相关产品推荐

