持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
这一期分享一下跨域问题,以及源码的简单分析
跨域问题解决代码
@Component
public class CrossOriginFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
return chain.filter(exchange);
}
}
源码分析
/**
* @author Spencer Gibb
* @author Ziemowit Stolarczyk
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
//GatewayLoadBalancerClientAutoConfiguration 网关需要使用的负载均衡
//GatewayClassPathWarningAutoConfiguration 检查是否配置我们webfux依赖
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
//加载了我们Gateway需要的注入的类。
public class GatewayAutoConfiguration {
//加载时间信息
@Bean
public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
return new StringToZonedDateTimeConverter();
}
//加载路由相关信息
@Bean
public RouteLocatorBuilder routeLocatorBuilder(
ConfigurableApplicationContext context) {
return new RouteLocatorBuilder(context);
}
//读取配置信息
@Bean
@ConditionalOnMissingBean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
GatewayProperties properties) {
return new PropertiesRouteDefinitionLocator(properties);
}
// 在内存注册的路由定义的Bean
@Bean
@ConditionalOnMissingBean(RouteDefinitionRepository.class)
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
return new InMemoryRouteDefinitionRepository();
}
@Bean
@Primary
public RouteDefinitionLocator routeDefinitionLocator(
List<RouteDefinitionLocator> routeDefinitionLocators) {
return new CompositeRouteDefinitionLocator(
Flux.fromIterable(routeDefinitionLocators));
}
//配置服务Bean,依赖 ConversionService转换服务(webFluxConversionService),与验证器
@Bean
public ConfigurationService gatewayConfigurationService(BeanFactory beanFactory,
@Qualifier("webFluxConversionService") ObjectProvider<ConversionService> conversionService,
ObjectProvider<Validator> validator) {
return new ConfigurationService(beanFactory, conversionService, validator);
}
/**
*GatewayProperties properties gateway的配置Bean
*List<GatewayFilterFactory> gatewayFilters 所有的过滤器,所有的实现在 学习2中有说明
*List<RoutePredicateFactory> predicates 路由断言工厂,所有的实现在 学习2中有说明
*RouteDefinitionLocator routeDefinitionLocator :这里注入的应该是 CompositeRouteDefinitionLocator的Bean,因为它是@primary的
* ConfigurationService configurationService 就是上面的ConfigurationService
* 由以上属性,生成一个 RouteDefinitionRouteLocator,
* RouteLocator 这个接口主要是一个 Flux<Route> getRoutes(); 即获取所有的路由
**/
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> predicates,
RouteDefinitionLocator routeDefinitionLocator,
ConfigurationService configurationService) {
return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
gatewayFilters, properties, configurationService);
}
@Bean
@Primary
@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
// TODO: property to disable composite?
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
return new CachingRouteLocator(
new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
//路由刷新的 监听器
@Bean
@ConditionalOnClass(
name = "org.springframework.cloud.client.discovery.event.HeartbeatMonitor")
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
//FilteringWebHandler webHanlder的过滤器,依赖 GlobalFilter全局过滤器
@Bean
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
return new FilteringWebHandler(globalFilters);
}
// 解读 spring.cloud.gateway.globalcors.*的配置的Bean
@Bean
public GlobalCorsProperties globalCorsProperties() {
return new GlobalCorsProperties();
}
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
//gateway的配置类
@Bean
public GatewayProperties gatewayProperties() {
return new GatewayProperties();
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ HystrixObservableCommand.class, RxReactiveStreams.class })
protected static class HystrixConfiguration {
@Bean
@ConditionalOnEnabledFilter
public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(
ObjectProvider<DispatcherHandler> dispatcherHandler) {
return new HystrixGatewayFilterFactory(dispatcherHandler);
}
@Bean
@ConditionalOnMissingBean(FallbackHeadersGatewayFilterFactory.class)
@ConditionalOnEnabledFilter
public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
return new FallbackHeadersGatewayFilterFactory();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class GatewayActuatorConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.actuator.verbose.enabled",
matchIfMissing = true)
@ConditionalOnAvailableEndpoint
public GatewayControllerEndpoint gatewayControllerEndpoint(
List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> routePredicates,
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator,
RouteDefinitionLocator routeDefinitionLocator) {
return new GatewayControllerEndpoint(globalFilters, gatewayFilters,
routePredicates, routeDefinitionWriter, routeLocator,
routeDefinitionLocator);
}
@Bean
@Conditional(OnVerboseDisabledCondition.class)
@ConditionalOnAvailableEndpoint
public GatewayLegacyControllerEndpoint gatewayLegacyControllerEndpoint(
RouteDefinitionLocator routeDefinitionLocator,
List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> routePredicates,
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {
return new GatewayLegacyControllerEndpoint(routeDefinitionLocator,
globalFilters, gatewayFilters, routePredicates, routeDefinitionWriter,
routeLocator);
}
}
private static class OnVerboseDisabledCondition extends NoneNestedConditions {
OnVerboseDisabledCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty(name = "spring.cloud.gateway.actuator.verbose.enabled",
matchIfMissing = true)
static class VerboseDisabled {
}
}
}
总结:
1. GatewayClassPathWarningAutoConfiguration 检查是否配置我们webfux依赖。
2. GatewayAutoConfiguration加载了我们Gateway需要的注入的类。
3. GatewayLoadBalancerClientAutoConfiguration 网关需要使用的负载均衡
4. GatewayRedisAutoConfiguration 网关整合Redis整合Lua实现限流
5. GatewayDiscoveryClientAutoConfiguration 服务注册与发现功能