找不到能够从类型 [com.google.protobuf.ByteString$LiteralByteString] 转换为类型 [java.lang.String] 的转换器

No converter found capable of converting from type [com.google.protobuf.ByteString$LiteralByteString] to type [java.lang.String]

您好,当我尝试使用自定义拦截器进行 openfeign 时,出现了一个 covnverter not found 错误。在接下来的部分中,我将详细介绍我所拥有的和所做的。

环境: spring-引导 2.2.5.RELEASE 和 2.2.6.RELEASE

google 秘密管理器和 openfeign

的依赖关系
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-secretmanager</artifactId>
    <version>1.2.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>

Feign 客户端界面

我遵循了 spring cloud openfeign

的文档
@FeignClient(value = "myClient", url = "${WEBSERVICE_PATH}", configuration = BasicAuthFeignConfiguration.class)
public interface MyClient {

    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> validate(@RequestHeader("Page-Description") String jwt, String request);
}

我的配置Class

这里属性文件中的AUTH_CREDENTIALS等于${sm://secret}

public class BasicAuthFeignConfiguration {

    @Value("${AUTH_CREDENTIALS}")
    private String authCredentials;

    @Bean
    public RequestInterceptor basicAuthRequestInterceptor(){
        return new CustomBasicAuthRequestInterceptor(authCredentials);
    } }

自定义拦截器

我创建了一个自定义拦截器,因为秘密管理器返回的凭据是 user:pass 格式,所以如果我使用默认的 BasicAuthRequestInterceptor 我会添加一个逻辑来拆分用户和密码以通过到构造函数并在内部它将再次以 user:pass 格式构建

public class CustomBasicAuthRequestInterceptor implements RequestInterceptor {

    private String headerValue;

    public CustomBasicAuthRequestInterceptor(String authCredentials, Charset charset){
        this.headerValue = "Basic " + Base64.getEncoder().encode(authCredentials.getBytes(Charset.forName("UTF-8")));

    }
    public CustomBasicAuthRequestInterceptor(String authCredentials){
        this(authCredentials, Charset.forName("UTF-8"));
    }

    @Override
    public void apply(RequestTemplate template) {
        template.header("Authorization", headerValue);
    }
}

所有这些都是我使用spring cloud open feign

的文档写的

我遇到的问题如下,当我在 运行 应用程序时出现此错误

{"message":"Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'basicAuthFeignConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.google.protobuf.ByteString$LiteralByteString] to type [java.lang.String]"}

我正在调试并注意到来自秘密管理器的转换器已加载,但是当假装客户端加载配置时没有转换器,因此它加载默认值并且该转换器不在默认值中。

如果我用 de @Configuration 注释 class 它会将 ByteString 解析为 String 但它适用于所有假客户端和我不想要的行为。

所以最后,有什么我遗漏的吗?我做错了什么?

我最近也遇到了类似的情况,扯了半天的毛,调试了这么久才搞定。首先,创建一个通用转换器。此代码在 Kotlin 中:

class GcpStringGenericConverter : GenericConverter {

    override fun getConvertibleTypes(): MutableSet<GenericConverter.ConvertiblePair> {
        return mutableSetOf(GenericConverter.ConvertiblePair(ByteString::class.java, String::class.java))
    }

    override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor): Any? {
        return (source as? ByteString)?.toString(UTF_8)
    }

}

之后,用 DefaultConversionService 注册这个转换器,对我来说唯一可能的方法是在启动 Spring 应用程序之前注册它。

fun main(args: Array<String>) {
    (DefaultConversionService.getSharedInstance() as? DefaultConversionService)?.addConverter(GcpStringGenericConverter())
    runApplication<MyApplication>(*args)
}