JavaEE鸿蒙应用开发HTML&JS+前端Python+大数据开发人工智能开发AI+设计软件测试新媒体+短视频直播运营产品经理集成电路应用开发(含嵌入式)Linux云计算+运维开发C/C++拍摄剪辑+短视频制作PMP项目管理认证电商运营Go语言与区块链大数据PHP工程师Android+物联网iOS.NET

【Java教程】feign动态设置数据源(https请求)

来源:黑马程序员

浏览13300人

2022.11.29

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}");
  }

总结:

这样就可以根据前端传来的参数,切换不同的客户端