当前位置: 首页 > 知识库问答 >
问题:

如何将属性源添加到Spring Cloud Stream Binder的环境中

翁文康
2023-03-14

我编写了一个PropertySource,它为spring启用类路径前缀。Kafka。属性。ssl。信任库。位置(不支持开箱即用)。本质上,这让我可以放置一个信任库。我的Spring Boot应用程序的src/main/resources文件夹中的jks,并从中引用它。jar文件。

这对于纯SpringKafka配置非常有效,如下所示:

spring:
  kafka:
    properties:
      ssl.truststore.location: classpath:myTruststore.jks

当在Spring Cloud Stream活页夹的上下文中给出相同的配置时,它当前会失败:

spring:
  cloud:
    stream:
      binders:
        my-binder:
         type: kafka
         environment:
           spring:
             kafka:
               properties:
                 ssl.truststore.location: classpath:myTruststore.jks

当我期望它以spring.cloud.stream.binders.my-binder.environment.spring.kafka.properties.ssl.truststore.location的poperty名称被调用时,我的Property tySource甚至没有被回调。

我认为我的PropertySource将执行类路径解析,它不是给定Spring Cloud Stream活页夹的环境的一部分。

问题:如何将PropertySources添加到特定绑定器的环境(或所有环境)?

谢啦!

编辑我在Spring Boot自动配置中添加我的属性源,如下所示:

@Configuration
@AutoConfigureBefore(KafkaAutoConfiguration.class)
@ConditionalOnProperty(name = "com.acme.kafka.enabled", matchIfMissing = true)
@EnableConfigurationPropertiesAcmeKafkaConfigurations.class)
public class AcmeKafkaAutoConfiguration {

  @Bean
  ClasspathResourceSupportEnablingPropertySource acmeKafkaClasspathResourceEnablingPropertySource(ConfigurableEnvironment environment) throws IOException {
    ClasspathResourcesSupport classpathResourcesSupport = new ClasspathResourcesSupport(Files.createTempDirectory(ACME_KAFKA_PREFIX));
    ClasspathResourceSupportEnablingPropertySource propertySource 
        = new ClasspathResourceSupportEnablingPropertySource(ClasspathResourceSupportEnablingPropertySource.NAME, environment, classpathResourcesSupport);
    environment.getPropertySources().addFirst(propertySource);
    return propertySource;
  }
}

编辑2:我尝试了Gary Russel下面的建议(使用声明为静态Bean方法的Bean后处理器)。

它可以工作,但在我的情况下,我在表单启动时会收到许多额外的警告日志:

[...]类型的Bean'...'没有资格被所有BeanPostProcess处理(例如:没有资格自动代理)

根据这篇文章,这可能会导致一些非常严重的副作用。

以下是我使用的代码(导致上述警告):

@Configuration
@AutoConfigureBefore(KafkaAutoConfiguration.class)
@ConditionalOnProperty(name = "com.acme.kafka.enabled", matchIfMissing = true)
@EnableConfigurationProperties(AcmeKafkaConfigurations.class)
public class AcmeKafkaAutoConfiguration {
  private static final String ACME_KAFKA_PREFIX = "acme.kafka.";

  @Bean
  @ConditionalOnMissingBean
  public static List<ConnectivityConfigurationsProvider> acmeKafkaTokenProviders(OAuth2TokenClient oAuthClient, AcmeKafkaConfigurations configuration) {
    List<ConnectivityConfigurationsProvider> connectivityConfigurationsProviders = new ArrayList<>();
    configuration.getInstances().forEach(serviceInstanceConfiguration -> {
      TokenProvider tokenProvider = new DefaultOAuth2TokenProvider(oAuthClient, serviceInstanceConfiguration);
      ConnectivityConfigurationsProvider connectivityConfigurationsProvider = new ConnectivityConfigurationsProvider(serviceInstanceConfiguration, tokenProvider);
      connectivityConfigurationsProviders.add(connectivityConfigurationsProvider);
    });
    return connectivityConfigurationsProviders;
  }

  @Bean
  @ConditionalOnMissingBean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public static OAuth2TokenClient acmeKafkaOAuth2TokenClient() {
    return new DefaultOAuth2TokenClient(new DefaultClientCredentialsTokenResponseClient());
  }

  @Bean
  public static ConnectivityConfigurationsProviders acmeKafkaConnectivityConfigurationsProviders(AcmeKafkaConfigurations configuration, List<ConnectivityConfigurationsProvider> connectivityConfigurationsProviders) {
    return new ConnectivityConfigurationsProviders(connectivityConfigurationsProviders);
  }

  @Bean
  static NoOpBeanPostProcessor springKafkaConfigurationsPropertySource(ConfigurableEnvironment environment, ConnectivityConfigurationsProviders connectivityConfigurationsProviders) {
    SpringKafkaConfigurationsPropertySource propertySource = new SpringKafkaConfigurationsPropertySource(SpringKafkaConfigurationsPropertySource.NAME, connectivityConfigurationsProviders);
    environment.getPropertySources().addLast(propertySource);
    return new NoOpBeanPostProcessor();
  }

  @Bean
  @ConditionalOnClass(name = "org.springframework.cloud.stream.binder.BinderConfiguration")
  static NoOpBeanPostProcessor springCloudStreamKafkaConfigurationsPropertySource(ConfigurableEnvironment environment, ConnectivityConfigurationsProviders connectivityConfigurationsProviders) {
    SpringCloudStreamKafkaConfigurationsPropertySource propertySource = new SpringCloudStreamKafkaConfigurationsPropertySource(SpringCloudStreamKafkaConfigurationsPropertySource.NAME, connectivityConfigurationsProviders);
    environment.getPropertySources().addLast(propertySource);
    return new NoOpBeanPostProcessor();
  }

  @Bean
  static NoOpBeanPostProcessor acmeKafkaConnectivityConfigurationsPropertySource(ConfigurableEnvironment environment, ConnectivityConfigurationsProviders connectivityConfigurationsProviders) {
    AcmeKafkaConnectivityConfigurationsPropertySource propertySource = new AcmeKafkaConnectivityConfigurationsPropertySource(AcmeKafkaConnectivityConfigurationsPropertySource.NAME, connectivityConfigurationsProviders);
    environment.getPropertySources().addLast(propertySource);
    return new NoOpBeanPostProcessor();
  }

  @Bean
  static NoOpBeanPostProcessor acmeKafkaClasspathResourceEnablingPropertySource(ConfigurableEnvironment environment) throws IOException {
    ClasspathResourcesSupport classpathResourcesSupport = new ClasspathResourcesSupport(Files.createTempDirectory(ACME_KAFKA_PREFIX));
    ClasspathResourceSupportEnablingPropertySource propertySource 
        = new ClasspathResourceSupportEnablingPropertySource(ClasspathResourceSupportEnablingPropertySource.NAME, environment, classpathResourcesSupport);
    environment.getPropertySources().addFirst(propertySource);
    return new NoOpBeanPostProcessor();
  }

  /**
   * This BeanPostProcessor does not really post-process any beans.
   * It is a way of getting the bean methods that add the property sources
   * above to be called early enough in the lifecycle of Spring ApplicationContext
   * creation. 
   * 
   * BeanPostProcessors are instantiated by Spring extremely early.
   * @Bean methods providing them should be declared as static methods.
   * See: https://stackoverflow.com/questions/30874244/bean-annotation-on-a-static-method 
   */
  static class NoOpBeanPostProcessor implements BeanPostProcessor, Ordered {
    @Override
    public int getOrder() {
      return Ordered.LOWEST_PRECEDENCE;
    }
  }
}

共有1个答案

宣弘新
2023-03-14

编辑

这似乎有效:

@SpringBootApplication
public class So61826877Application {

    private static final String KEY = "spring.cloud.stream.binders.my-binder.environment."
            + "spring.kafka.properties.ssl.truststore.location";

    public static void main(String[] args) {
        SpringApplication.run(So61826877Application.class, args);
    }

    @Bean
    public static BeanPostProcessor configureSource(ConfigurableEnvironment env) {
        Properties source = new Properties();
        System.out.println(env.getProperty(KEY));
        source.setProperty(KEY, "/path/to/myTruststore.jks");
        env.getPropertySources().addFirst(new PropertiesPropertySource("cp", source));
        return new MyBpp();
    }

    @Bean
    Consumer<String> input() {
        return System.out::println;
    }

}

class MyBpp implements BeanPostProcessor, Ordered {

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }

}
classpath:myTruststore.jks
...
ConsumerConfig values: 
    allow.auto.create.topics = true
    auto.commit.interval.ms = 100
    ...
    ssl.truststore.location = /path/to/myTruststore.jks
    ...
 类似资料:
  • 问题内容: 如何添加到特定内容?不起作用。 问题答案: jQuery <1.9 jQuery 1.9以上

  • 我想在我的< code >上添加属性 似乎路线路径确实与问号混淆了。如果我把它换成其他东西,比如一个符号戳,它就会“起作用”。然而,这不是我想要的格式。我想要常规的<代码> 我找不到关于如何使这样的东西工作的文档。我看到了一些关于url的部分的东西,但我不太理解它。 谢谢你的所有帮助

  • 我的目标是将自定义属性源添加到Spring-Cloud-server。我想实现的是在Spring-Cloud-config-Client应用程序中从该自定义源获得一些自定义属性。 根据在sping-config-server中添加环境存储库的建议,我已经创建了应用程序和单独的项目。第二个是基于sping-Cloud-consul-config代码的。因此,我已经创建了所有必要的类,如,,等等,并在

  • 我们正在使用带有支持git存储库的Spring云配置服务器来为测试配置文件提供属性。我们收到了将密钥移动到vault(hashicorp)并像往常一样在属性文件中保留常规属性的要求。 在拥有vault之前,我们通过系统属性(使用)传递密钥,该属性作为常规属性源加载,应用程序按预期工作。 现在我必须有一个复合属性源来同时从属性文件和vault中获取。我不确定如何同时从vault和git中提取属性并将

  • 问题内容: 在node.js项目上使用新的VSCode编辑器。我正在尝试通过编辑launch.json文件来配置“启动”配置文件以进行调试。我需要将连接字符串设置为环境变量。根据launch.json文件中的注释: 我试过像这样添加我的环境变量: 当我尝试启动我的应用程序时,这会导致错误;“ OpenDebug进程意外终止”。我尚未找到任何可以解释问题所在的日志文件等。 我知道当我设置环境变量并从

  • 问题内容: 我已经安装了jre8并将其设置为jre的默认值,但是在编译器合规性下我找不到1.8,而在执行环境下我找不到javaSE 1.8。我正在使用最新版本的Eclipse EE。 我看了一下本手册 http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask- add_new_jr