gpt4 book ai didi

spring-boot - spring boot : same feign client interface, 具有不同属性的多个实例

转载 作者:行者123 更新时间:2023-12-05 06:08:04 28 4
gpt4 key购买 nike

我有一个带有此界面的 feignClient:

@FeignClient(
name = "kmr-api",
url = "${client.kmr.url}",
configuration = KmrClient.KmrClientConfiguration.class
)
public interface KmrClient {
@Configuration
class KmrClientConfiguration {
@Value("${client.kmr.access-token-uri}")
private String accessTokenUri;

@Value("${client.kmr.client-id}")
private String clientId;

// ...

@Bean
public Feign.Builder feignBuilder() {
return Feign.builder()
.retryer(Retryer.NEVER_RETRY)
.options(new Request.Options(connectTimeoutMillis, readTimeoutMillis));
}

private OAuth2ProtectedResourceDetails resource() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(this.accessTokenUri);
resourceDetails.setClientId(this.clientId);
resourceDetails.setClientSecret(this.clientSecret);
// ...
return resourceDetails;
}

@Component
class KmrApiBrandRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("brand", "renault");
}
}
}

@RequestMapping(value = "/vehicle/summary", method = RequestMethod.POST)
VehicleSummary getVehicleSummary(@RequestBody KmrVehicleId2 kmrVehicleId);
}

以及相关的属性,例如

# Feign service
client.kmr.url=https://example/api/v1
client.kmr.access-token-uri=https://example/oauth2/access_token
client.kmr.client-id=myclientid

现在,我需要此 KmrClient 的多个实例,它们具有完全相同的界面和配置,但具有不同的属性。例如,我正在尝试找出可以像这样解决的问题:

# Feign service
client.kmr[0].url=https://example/api/v1
client.kmr[0].access-token-uri=https://example/oauth2/access_token
client.kmr[0].client-id=myclientid
# Feign service
client.kmr[1].url=https://example/api/v1
client.kmr[1].access-token-uri=https://example/oauth2/access_token
client.kmr[1].client-id=myclientid
# there are 4 instances in total, one per region supported in app

从这里我不知道如何加载 client.kmr[1] 中的每个属性并将它们连接到不同的配置和客户端。

我怎样才能达到这个结果?

最佳答案

这是我最终找到的解决方案:

首先,我创建了自己的配置类来保存属性值:

@ConfigurationProperties(prefix = "client.kdiag")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class KdiagClientsProperties {
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class KdiagClientProperties {
String url;
String accessTokenUri;
String clientId;
String clientSecret;
String scope;
int connectTimeoutMillis = 10000;
int readTimeoutMillis = 15000;
}

Map<String, KdiagClientProperties> regions;
}

.properties 看起来像这样:

client.kdiag.regions.EU.url=https://example.io/diag/api/v1
client.kdiag.regions.EU.access-token-uri=https://example.org/auth/oauth2/stuff/access_token
client.kdiag.regions.EU.client-id=redacted
client.kdiag.regions.EU.client-secret=redacted
client.kdiag.regions.EU.scope=scope1,scope2

client.kdiag.regions.RU.url=https://example.io/diag/api/v1
client.kdiag.regions.RU.access-token-uri=https://example.org/auth/oauth2/stuff/access_token
client.kdiag.regions.RU.client-id=redacted
client.kdiag.regions.RU.client-secret=redacted
client.kdiag.regions.RU.scope=scope1,scope2

然后我创建了一个名为 KmrClients 的类,用于访问读取这些属性的所有客户端实例:

/**
* Allow requesting each Kdiag region.
*
* Get the kdiag client with @{@link KdiagClients#clientByRegion(KdisRegion)}
*/
@Order(SecurityProperties.IGNORED_ORDER)
@Configuration
@EnableConfigurationProperties(value = {KdiagClientsProperties.class})
@Import(FeignClientsConfiguration.class) // We need these to reinject decoder, encoder, contract in constructor
@Slf4j
public class KdiagClients {
private Map<String, KdiagClient> clients;

/**
* builds the OAuth2 configuration for a client
*/
private OAuth2ProtectedResourceDetails resource(KdiagClientsProperties.KdiagClientProperties properties) {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(properties.getAccessTokenUri());
resourceDetails.setClientId(properties.getClientId());
resourceDetails.setClientSecret(properties.getClientSecret());
resourceDetails.setScope(Arrays.asList(properties.getScope().split(",")));
resourceDetails.setGrantType("client_credentials");
return resourceDetails;
}

@Autowired
public KdiagClients(
KdiagClientsProperties properties,
Decoder decoder,
Encoder encoder,
Contract contract
) {
Assert.notEmpty(properties.regions, "No KDiag region clients defined in properties (ex: kdiag.client.regions.EU etc) ");
log.info("found kdiag clients for regions:" + properties.regions.keySet().toString());
this.clients = properties.getRegions().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, clientPropertiesEntry -> {
return Feign.builder()
.retryer(Retryer.NEVER_RETRY)
.options(new Request.Options(clientPropertiesEntry.getValue().getConnectTimeoutMillis(), clientPropertiesEntry.getValue().getReadTimeoutMillis()))
.requestInterceptor(new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), resource(clientPropertiesEntry.getValue())))
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.target(KdiagClient.class, clientPropertiesEntry.getValue().getUrl());
}));
}

public KdiagClient clientByRegion(KdisRegion region) {
if (this.clients.containsKey(region.name())) {
return this.clients.get(region.name());
} else {
throw new NoKdiagClientForRegionException(region);
}
}

}

最后注入(inject)KdiagClients就可以使用了:

this.kdiagClients.clientByRegion(KdisRegion.EU)

此解决方案有点特定于某个领域,但可以对其进行调整以满足其需要。所以最后的解决方案是:

  • 创建自定义配置属性
  • 创建一个面向类,手动实例化 FeignClients 读取配置属性

关于spring-boot - spring boot : same feign client interface, 具有不同属性的多个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65183172/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com