1、背景
在使用springboot-feign/spingcloud-feign时,需要在启动springboot的时候,注入的方式将feigncofing配置好,也就是说项目启动以后只能有一个数据源,且不能修改,在网上找了很多资料没有找到解决方案(网上应该有,只是我没有找到),后面只能是硬着头皮看源码,问题解决
2、代码
其实在这里用的原生的feign,并不是springboot/springcloud封装的feign,废话不说,上代码
public final class HttpsUtil {
public static T getRemote(Class apiType, String url, String apiCert, String certPassWord) {
// apiCert 是p12文件读了以后的数据,可以把p12文件放在本地,我这里是伪代码了
feign.Client.Default client = FeignClient(apiCert, certPassWord);
Decoder decoder =
(response, type) -> {
final String result =
IOUtils.toString(response.body().asInputStream(), StandardCharsets.UTF_8);
if (String.class.getName() == type.getTypeName()) {
return result;
}
try {
return JSON.parseObject(result, type);
} catch (Exception e) {
log.error("json parse exception");
}
return result;
};
ErrorDecoder errorDecoder =
(methodKey, response) -> {
try {
final String result =
IOUtils.toString(response.body().asInputStream(), StandardCharsets.UTF_8);
log.info("feign client decoder response body : {}", result);
throw new SysStatusException(response.status(), result);
} catch (IOException e) {
log.info("feign client decoder response error {}", e);
}
throw new BizStatusException(response.status(), BizCommMessage.ERROR_MSG);
};
T remote =
Feign.builder()
.decoder(decoder)
.errorDecoder(errorDecoder)
.client(url)
.target(apiType, client);
return remote;
}
public static Client getFeignClient(String apiCert, String certPassWord) {
final SSLSocketFactory sslSocketFactory = getSSLSocketFactory(apiCert, certPassWord);
feign.Client.Default aDefault = new Client.Default(sslSocketFactory, new NoopHostnameVerifier());
return aDefault;
}
public static SSLSocketFactory getSSLSocketFactory(String apiCert, String certPassWord) {
byte[] bytes = apiCert.getBytes();
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(inputStream, certPassWord.toCharArray());
SSLContext sslContext =
SSLContexts.custom()
// 忽略掉对服务器端证书的校验,特别重要,被这行代码坑过
.loadTrustMaterial((TrustStrategy) (chain, authType) -> true)
.loadKeyMaterial(keyStore, certPassWord.toCharArray())
.build();
return sslContext.getSocketFactory();
} catch (IOException e) {
log.error("=======init feign client throw IOException======={}", e);
} catch (KeyStoreException e) {
log.error("=======init feign client throw KeyStoreException======={}", e);
} catch (UnrecoverableKeyException e) {
log.error("=======init feign client throw UnrecoverableKeyException======={}", e);
} catch (CertificateException e) {
log.error("=======init feign client throw CertificateException======={}", e);
} catch (NoSuchAlgorithmException e) {
log.error("=======init feign client throw NoSuchAlgorithmException======={}", e);
} catch (KeyManagementException e) {
log.error("=======init feign client throw KeyManagementException======={}", e);
}
return null;
}
}
2.2、 编写请求方法
public interface TestRemote {
@Override
@RequestLine("POST /apis/{test}/query")
@Headers({"Content-Type: application/json","Accept: application/json"})
@Body("{body}")
String query(@Param("test") String test, @Param("body") String body);
}
2.3、发送请求
public static void main(String[] args) {
TestRemote testRemote = HttpsUtil.getRemote(TestRemote.class,String url, String apiCert, String certPassWord);
testRemote.query("test","{"id":1}");
}
总结:
这样就可以根据前端传来的参数,切换不同的客户端