From cecc402a3b04769171e785adf0142220ff63b898 Mon Sep 17 00:00:00 2001 From: "yuxin.wang" Date: Fri, 22 Dec 2023 11:27:25 +0800 Subject: [PATCH 1/2] feature: config support profile and multiple values (#3552) 'spring.config.import with nacos' support profile and multiple values --- .../NacosConfigDataLocationResolver.java | 37 +++++++++++++++---- .../configdata/NacosConfigDataResource.java | 12 +++++- .../NacosConfigDataLocationResolverTest.java | 28 ++++++++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolver.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolver.java index 2f541b97be..844675a59e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolver.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolver.java @@ -51,6 +51,7 @@ * {@link ConfigDataResource}. * * @author freeman + * @author yuxin.wang * @since 2021.0.1.0 */ public class NacosConfigDataLocationResolver @@ -152,28 +153,50 @@ public List resolveProfileSpecific( registerConfigManager(properties, bootstrapContext); - return loadConfigDataResources(location, profiles, properties); + return loadConfigDataResources(location.split(), profiles, properties); } private List loadConfigDataResources( - ConfigDataLocation location, Profiles profiles, + ConfigDataLocation[] configDataLocations, Profiles profiles, NacosConfigProperties properties) { List result = new ArrayList<>(); + for (ConfigDataLocation configDataLocation: configDataLocations) { + result.add(loadConfigDataResource(configDataLocation, profiles, null, properties)); + for (String profile: profiles) { + result.add(loadConfigDataResource(getProfileConfigDataLocation(configDataLocation, profile), + profiles, profile, properties)); + } + } + return result; + } + + ConfigDataLocation getProfileConfigDataLocation(ConfigDataLocation configDataLocation, String profile) { + StringBuilder profileResourceLocation = new StringBuilder( + configDataLocation.isOptional() ? ConfigDataLocation.OPTIONAL_PREFIX : ""); + String resourceLocation = configDataLocation.getValue(); + int paramIndex = resourceLocation.indexOf('?') < 0 ? resourceLocation.length() : resourceLocation.indexOf('?'); + int extensionIndex = resourceLocation.lastIndexOf('.', paramIndex); + profileResourceLocation.append(resourceLocation, 0, extensionIndex > 0 ? extensionIndex : paramIndex); + profileResourceLocation.append('-').append(profile); + profileResourceLocation.append(resourceLocation.substring(extensionIndex > 0 ? extensionIndex : paramIndex)); + return ConfigDataLocation.of(profileResourceLocation.toString()); + } + + private NacosConfigDataResource loadConfigDataResource( + ConfigDataLocation location, Profiles profiles, String profile, + NacosConfigProperties properties) { URI uri = getUri(location, properties); if (StringUtils.isBlank(dataIdFor(uri))) { throw new IllegalArgumentException("dataId must be specified"); } - NacosConfigDataResource resource = new NacosConfigDataResource(properties, - location.isOptional(), profiles, log, + return new NacosConfigDataResource(properties, + location.isOptional(), profiles, profile, log, new NacosItemConfig().setGroup(groupFor(uri, properties)) .setDataId(dataIdFor(uri)).setSuffix(suffixFor(uri, properties)) .setRefreshEnabled(refreshEnabledFor(uri, properties)) .setPreference(preferenceFor(uri))); - result.add(resource); - - return result; } private String preferenceFor(URI uri) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataResource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataResource.java index b5ff864b1b..341fbb2ce3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataResource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataResource.java @@ -28,6 +28,7 @@ /** * @author freeman + * @author yuxin.wang * @since 2021.0.1.0 */ public class NacosConfigDataResource extends ConfigDataResource { @@ -36,6 +37,8 @@ public class NacosConfigDataResource extends ConfigDataResource { private final boolean optional; + private final String profile; + private final Profiles profiles; private final Log log; @@ -43,10 +46,11 @@ public class NacosConfigDataResource extends ConfigDataResource { private final NacosItemConfig config; public NacosConfigDataResource(NacosConfigProperties properties, boolean optional, - Profiles profiles, Log log, NacosItemConfig config) { + Profiles profiles, String profile, Log log, NacosItemConfig config) { this.properties = properties; this.optional = optional; this.profiles = profiles; + this.profile = profile; this.log = log; this.config = config; } @@ -63,6 +67,10 @@ public String getProfiles() { return StringUtils.collectionToCommaDelimitedString(getAcceptedProfiles()); } + public String getProfile() { + return profile; + } + List getAcceptedProfiles() { return this.profiles.getAccepted(); } @@ -97,7 +105,7 @@ public int hashCode() { @Override public String toString() { return "NacosConfigDataResource{" + "properties=" + properties + ", optional=" - + optional + ", profiles=" + profiles + ", config=" + config + '}'; + + optional + ", profiles=" + profiles + ", profile=" + profile + ", config=" + config + '}'; } public static class NacosItemConfig { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java index 7928af2256..54f0a6c64b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java @@ -45,6 +45,7 @@ * NacosConfigDataLocationResolver Tester. * * @author freeman + * @author yuxin.wang */ public class NacosConfigDataLocationResolverTest { @@ -237,4 +238,31 @@ private NacosConfigDataResource testResolveProfileSpecific(String activeProfile) return resources.get(0); } + @Test + void testGetProfileConfigDataLocationIsOK() { + String[] locations = new String[]{ + "nacos:nacos.yaml", + "optional:nacos:nacos.yaml", + "optional:nacos:nacos.yaml?group=DEFAULT_GROUP", + "optional:nacos:nacos.yaml?group=DEFAULT.GROUP", + "optional:nacos:nacos", + "optional:nacos:nacos?group=DEFAULT_GROUP", + "optional:nacos:nacos?group=DEFAULT.GROUP" + }; + String[][] profileLocations = new String[][]{ + new String[]{"nacos:nacos-profile.yaml", "false"}, + new String[]{"nacos:nacos-profile.yaml", "true"}, + new String[]{"nacos:nacos-profile.yaml?group=DEFAULT_GROUP", "true"}, + new String[]{"nacos:nacos-profile.yaml?group=DEFAULT.GROUP", "true"}, + new String[]{"nacos:nacos-profile", "true"}, + new String[]{"nacos:nacos-profile?group=DEFAULT_GROUP", "true"}, + new String[]{"nacos:nacos-profile?group=DEFAULT.GROUP", "true"}, + }; + for (int i = 0; i < locations.length; i++) { + ConfigDataLocation configDataLocation = ConfigDataLocation.of(locations[i]); + ConfigDataLocation profileConfigDataLocation = this.resolver.getProfileConfigDataLocation(configDataLocation, "profile"); + assertThat(profileConfigDataLocation.getValue()).isEqualTo(profileLocations[i][0]); + assertThat(profileConfigDataLocation.isOptional()).isEqualTo(Boolean.parseBoolean(profileLocations[i][1])); + } + } } From 84718dbf660fa9ae4fbf67f051b42a33f25a2a54 Mon Sep 17 00:00:00 2001 From: "yuxin.wang" Date: Wed, 27 Dec 2023 10:59:37 +0800 Subject: [PATCH 2/2] update NacosConfigDataLocationResolver UT --- .../configdata/NacosConfigDataLocationResolverTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java index 54f0a6c64b..32ff43108d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/configdata/NacosConfigDataLocationResolverTest.java @@ -199,6 +199,7 @@ void testCommonPropertiesHasLowerPriority() { private List testUri(String locationUri, String... activeProfiles) { Profiles profiles = mock(Profiles.class); + when(profiles.iterator()).thenReturn(Collections.emptyIterator()); when(profiles.getActive()).thenReturn(Arrays.asList(activeProfiles)); return this.resolver.resolveProfileSpecific(context, ConfigDataLocation.of(locationUri), profiles); @@ -210,8 +211,10 @@ void whenNoneInBootstrapContext_thenCreateNewConfigClientProperties() { .thenReturn(false); when(bootstrapContext.get(eq(NacosConfigProperties.class))) .thenReturn(new NacosConfigProperties()); + Profiles profiles = mock(Profiles.class); + when(profiles.iterator()).thenReturn(Collections.emptyIterator()); List resources = this.resolver.resolveProfileSpecific( - context, ConfigDataLocation.of("nacos:test.yml"), mock(Profiles.class)); + context, ConfigDataLocation.of("nacos:test.yml"), profiles); assertThat(resources).hasSize(1); verify(bootstrapContext, times(0)).get(eq(NacosConfigProperties.class)); NacosConfigDataResource resource = resources.get(0); @@ -225,6 +228,7 @@ private NacosConfigDataResource testResolveProfileSpecific() { private NacosConfigDataResource testResolveProfileSpecific(String activeProfile) { Profiles profiles = mock(Profiles.class); + when(profiles.iterator()).thenReturn(Collections.emptyIterator()); if (activeProfile != null) { when(profiles.getActive()) .thenReturn(Collections.singletonList(activeProfile));