Java 如何将Spring Retry与带Vault PropertySource的Spring Vault配置一起使用?

Java 如何将Spring Retry与带Vault PropertySource的Spring Vault配置一起使用?,java,spring,spring-boot,spring-vault,Java,Spring,Spring Boot,Spring Vault,我希望标记为vault PropertySource的spring vault配置能够在请求失败时重试对vault的请求。 我应该将什么标记为可重试?我正在使用Spring重试,我正在查看 没有可见的方法标记为可重试。我是否应该更改Vault模板的实现并将Vault操作标记为可重试 ProvisioningSecrets.java @Configuration @VaultPropertySource( value="secret/provisioning

我希望标记为vault PropertySource的spring vault配置能够在请求失败时重试对vault的请求。 我应该将什么标记为可重试?我正在使用Spring重试,我正在查看

没有可见的方法标记为可重试。我是否应该更改Vault模板的实现并将Vault操作标记为可重试

ProvisioningSecrets.java

    @Configuration
    @VaultPropertySource(
            value="secret/provisioning",
            propertyNamePrefix = "provisioning.",
            renewal = Renewal.RENEW
            )
    @EnableRetry
    @Lazy
    @Profile("!test")
    public class ProvisioningSecrets {
        private static final Logger logger = LoggerFactory.getLogger(ProvisioningSecrets.class);

        @Autowired
        public void setPassword(@Value("${provisioning.password}") final String password) throws Exception {
            logger.info("We successfully set the provisioning db password.");
            EnvVars.changeSetting(Setting.PROVISIONING_PASS, password);
        }

        @Autowired
        public void setHost(@Value("${provisioning.host}") final String host) throws Exception {
            logger.info("We successfully set the provisioning db host.");
            EnvVars.changeSetting(Setting.PROVISIONING_HOST, host);
        }

        @Autowired
        public void setPort(@Value("${provisioning.port}") final int port) throws Exception {
            logger.info("We successfully set the provisioning db port.");
            EnvVars.changeSetting(Setting.PROVISIONING_PORT, Integer.toString(port));
        }

        @Autowired
        public void setUsername(@Value("${provisioning.username}") final String username) throws Exception {
            logger.info("We successfully set the provisioning db username.");
            EnvVars.changeSetting(Setting.PROVISIONING_USER, username);
        }

        @Autowired
        public void setDbName(@Value("${provisioning.name}") final String name) throws Exception {
            logger.info("We successfully set the provisioning db name.");
            EnvVars.changeSetting(Setting.PROVISIONING_DB_NAME, name);
        }
    }
VaultConfiguration.java

@Configuration
@Profile("!test")
public class VaultConfiguration extends AbstractVaultConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(VaultConfiguration.class);

    private URI vaultHost;

    private String vaultToken;

    /**
     * Configure the Client Authentication.
     *
     * @return A configured ClientAuthentication Object.
     * @see ClientAuthentication
     */
    @Override
    public ClientAuthentication clientAuthentication() {
        // testing out environment variable value injection
        logger.debug("Vault Token configuration done.");
        return new TokenAuthentication(vaultToken);
    }

    @Override
    @Bean
    @DependsOn("vaultToken")
    public SessionManager sessionManager() {
        return super.sessionManager();
    }

    @Override
    public SslConfiguration sslConfiguration() {
        logger.info("Configuring Vault SSL with NONE.");
        return SslConfiguration.NONE;
    }

    /**
     * Specify an endpoint for connecting to Vault.
     *
     * @return A configured VaultEndpoint.
     * @see VaultEndpoint
     */
    @Override
    public VaultEndpoint vaultEndpoint() {
        logger.debug("Vault Host:" + vaultHost.toString());

        if (vaultHost.toString().isEmpty()) {
            logger.info("Creating default Vault Endpoint.");
            return new VaultEndpoint();
        }

        logger.info("Creating Vault Endpoint based on address: " + vaultHost.toString());
        final VaultEndpoint endpoint = VaultEndpoint.from(vaultHost);
        logger.info("Created Vault Endpoint: " + endpoint.toString());

        return endpoint;
    }

    @Bean("vaultHost")
    public URI vaultHost(@Value("${spring.vault.host}") final URI vaultHost) {
        this.vaultHost = vaultHost;
        return vaultHost;
    }

    @Override
    @Bean
    @DependsOn("vaultHost")
    public VaultTemplate vaultTemplate() {
        return super.vaultTemplate();
    }

    @Bean("vaultToken")
    public String vaultToken(@Value("${spring.vault.token}") final String vaultToken) {
        this.vaultToken = vaultToken;
        return vaultToken;
    }
}

使用
RetryTemplate
创建自定义
VaultTemplate
bean类怎么样

public class RetryableVaultTemplate extends VaultTemplate {

    private final RetryTemplate retryTemplate;

    public RetryableVaultTemplate(VaultEndpointProvider endpointProvider,
            ClientHttpRequestFactory clientHttpRequestFactory,
            SessionManager sessionManager, RetryTemplate retryTemplate) {
        super(endpointProvider, clientHttpRequestFactory, sessionManager);
        this.retryTemplate = retryTemplate;
    }

    @Override
    public VaultResponse read(final String path) {

        return retryTemplate
                .execute(new RetryCallback<VaultResponse, RuntimeException>() {
                    @Override
                    public VaultResponse doWithRetry(RetryContext context) {
                        System.out.println("doWithRetry");
                        return RetryableVaultTemplate.super.read(path);
                    }
                });
    }

    @Override
    public <T> VaultResponseSupport<T> read(final String path, final Class<T> responseType) {

        return retryTemplate
                .execute(new RetryCallback<VaultResponseSupport<T>, RuntimeException>() {
                    @Override
                    public VaultResponseSupport<T> doWithRetry(RetryContext context) {
                        return RetryableVaultTemplate.super.read(path, responseType);
                    }
                });
    }
}
public类RetryableVaultTemplate扩展了VaultTemplate{
私有最终RetryTemplate RetryTemplate;
public RetryableVaultTemplate(VaultEndpointProvider,
ClientHttpRequestFactory ClientHttpRequestFactory,
会话管理器会话管理器,RetryTemplate(RetryTemplate){
超级(endpointProvider、clientHttpRequestFactory、sessionManager);
this.retryTemplate=retryTemplate;
}
@凌驾
公共Vault响应读取(最终字符串路径){
返回retryTemplate
.execute(new RetryCallback(){
@凌驾
公共Vault响应doWithRetry(RetryContext上下文){
System.out.println(“doWithRetry”);
返回RetryableVaultTemplate.super.read(路径);
}
});
}
@凌驾
公共Vault响应支持读取(最终字符串路径、最终类响应类型){
返回retryTemplate
.execute(new RetryCallback(){
@凌驾
公共Vault响应支持doWithRetry(RetryContext上下文){
返回RetryableVaultTemplate.super.read(路径,响应类型);
}
});
}
}

确保将这个bean类注册为
vaultTemplate
bean,而不是
vaultTemplate

我用@Component(“vaultTemplate”)注释该类,Spring会自动检测并使用它吗?我的Vault配置类中是否应该有@Autowired VaultTemplate VaultTemplate?感谢您的广泛响应,欢迎您假期归来,新年快乐到目前为止,我所取得的成就是:我配置并使用了SimpleRetryPolicy和ExponentialBackOffPolicy。我必须知道我的实现是否正确,是否正确。你能看一下我的实现吗?请忽略重试和退避策略的硬编码配置,如果您能建议如何从application.yml属性进行配置,我将不胜感激。我会在pastebin上发布代码。RetryableVaultTemplate:。Vault配置:。我知道spring retry不会处理404错误,我们如何配置RestTemplate或HttpClient在此类HTTP状态下重试?如在。我们如何向RetryableVaultTemplate clientHttpRequestFactory提供自定义的HttpMethodRetryHandler?我设法从```@覆盖公共Vault响应doWithRetry(RetryContext上下文){logger.debug(“log me doWithRetry”);VaultResponse=RetryableVaultTemplate.super.read(path);如果(response!=null){return response;}抛出新的RuntimeException(“收到空响应,可能是404”);}}}```在Vault模板中,read方法正在检查HttpStatus.NOT\u是否找到并返回null。我检查了null,并抛出了一个带有“收到空响应。可能是404”消息的RuntimeException。如果能够捕捉到实际的异常,那就太好了。我该怎么做?做这件事的优雅方法是什么?