feign踩坑_springboot2.x引入feign踩的坑

本文记录了在SpringBoot2.x项目中集成Feign以调用第三方服务接口的过程。首先介绍了Feign的基本概念,它是SpringCloud中的一个声明式Web服务客户端,简化了微服务间的调用。然后,对比了SpringBoot1.x和2.x中Feign的不同引入方式,并分享了在SpringBoot2.x项目中遇到的引入失败问题及解决方案,涉及SpringCloud OpenFeign和Hystrix的相关依赖配置。

springboot2.x引入feign

一、需求

最近公司项目需求,需要调用第三方服务的接口,所以选用了feign来实现(这里只说springboot2.x的pom引用,没有怎么使用,网上一大顿)。

二、什么是feign

feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

三、springboot1.x中feign的使用(这里不展示hystrix熔断的配置和实现)

3.1 在pom.xml中加入依赖

org.springframework.cloud

spring-cloud-starter-feign

1.2.2.RELEASE

org.springframework.cloud

spring-cloud-starter-hystrix

1.2.3.RELEASE

org.springframework.cloud

spring-cloud-starter-hystrix-dashboard

1.2.3.RELEASE

3.2 在启动类上添加注解@EnableFeignClients

@EnableCaching

@EnableAutoConfiguration

@SpringBootApplication

@EnableConfigurationProperties

@ServletComponentScan//配置druid必须加的注解,如果不加,访问页面打不开,filter和servlet、listener之类的需要单独进行注册才能使用,spring boot里面提供了该注解起到注册作用

@EnableTransactionManagement

@EnableFeignClients

@EnableHystrix

@EnableCircuitBreaker

@EnableHystrixDashboard

public class App {

public static void main(String[] args) {

SpringApplication.run(App.class, args);

}

}

3.3 启动springboot的启动类

四、springboot2.x中feign的使用(这里不展示hystrix熔断的配置和实现)

在另外项目中引用的时候用的是spring2.x,所以就出现问题了,引入feign失败。网上说springboot2.x需要如下引入:

org.springframework.cloud

spring-cloud-starter-openfeign

但是我使用openfeign在启动的时候报错:

所以我将pom.xml的依赖改成了这样(一定要注释掉):

org.springframework.cloud

spring-cloud-starter-openfeign

org.springframework.cloud

spring-cloud-starter-hystrix

1.2.3.RELEASE

org.springframework.cloud

spring-cloud-starter-hystrix-dashboard

1.2.3.RELEASE

spring-milestones

Spring Milestones

https://repo.spring.io/libs-milestone

false

org.springframework.cloud

spring-cloud-openfeign

2.0.0.RC1

pom

import

启动类注解和springboot1.x中的一样,启动工程,就可以了。

此篇只是工作中问题的记录,有理解更深的朋友,欢迎告诉我。

<think>我们正在解决在Spring Boot 3.x中配置Feign客户端使用HTTPS协议的问题。用户之前遇到了PKIX路径构建失败的错误,但当前问题是如何配置Feign使用HTTPS。 由于Feign在底层通常使用HTTP客户端(如Apache HttpClient或OKHttp),我们需要确保这些客户端能够正确处理HTTPS请求,特别是当目标服务器使用自签名证书或不受信任的证书时。 解决方案: 1. 如果目标服务器使用公共信任的证书,则无需特殊配置,Feign客户端可以直接使用HTTPS。 2. 如果目标服务器使用自签名证书或不被JVM信任的证书,我们可以通过以下方式之一解决: a. 将目标服务器的证书导入到JVM的信任库(推荐用于生产环境)。 b.Feign客户端配置中忽略SSL证书验证(仅用于开发测试环境)。 由于用户之前遇到PKIX错误,我们假设目标服务器证书不被信任。因此,我们将提供两种配置Feign客户端的方法: 方法一:配置Feign使用自定义的SSL上下文(通过Apache HttpClient) 方法二:配置Feign使用OKHttp并设置信任所有证书(不推荐用于生产) 我们以方法一(使用Apache HttpClient)为例,因为Spring Cloud OpenFeign默认支持Apache HttpClient。 步骤: 1. 添加Apache HttpClient依赖 2. 配置一个自定义的HttpClient,该客户端使用信任所有证书的SSL上下文(或者也可以配置为信任指定证书) 3. 配置Feign使用这个自定义的HttpClient 注意:在Spring Boot 3.x中,我们使用Spring Cloud 2022.x(代号Kilburn),它基于Spring Framework 6和Java 17。 具体代码实现: 第一步:添加依赖(如果尚未添加) 在pom.xml中添加: ```xml <!-- Feign with Apache HttpClient --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> </dependency> ``` 第二步:配置自定义的HttpClient 我们可以创建一个配置类,配置一个忽略SSL验证的HttpClient(仅用于测试环境): ```java import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.core5.ssl.SSLContextBuilder; import org.apache.hc.core5.ssl.TrustStrategy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.net.ssl.SSLContext; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; @Configuration public class FeignConfig { @Bean public CloseableHttpClient httpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { // 信任所有证书 TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial(null, acceptingTrustStrategy) .build(); SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext); HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() .setSSLSocketFactory(sslSocketFactory) .build(); return HttpClients.custom() .setConnectionManager(connectionManager) .evictExpiredConnections() .build(); } } ``` 第三步:在Feign客户端接口上使用配置 在Feign客户端接口上,我们可以指定配置类(如果我们需要将自定义的HttpClient应用到特定的Feign客户端): ```java import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "exampleClient", url = "https://example.com", configuration = FeignConfig.class) public interface ExampleClient { @GetMapping("/api/data") String getData(); } ``` 但是,上面的配置会应用到所有Feign客户端(因为我们在配置类中定义了全局的HttpClient Bean)。如果我们只想为特定客户端配置,可以创建不同的HttpClient Bean,并通过@Qualifier指定。 另外,我们也可以使用默认的Feign配置,因为Spring Cloud OpenFeign会自动使用我们定义的CloseableHttpClient Bean(类型为CloseableHttpClient)作为HTTP客户端。 方法二:使用OKHttp(可选) 如果我们想使用OKHttp,可以添加OKHttp依赖并配置一个信任所有证书的OkHttpClient。 添加依赖: ```xml <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> ``` 配置OKHttpClient Bean: ```java import okhttp3.OkHttpClient; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.concurrent.TimeUnit; @Bean public OkHttpClient okHttpClient() { try { // 创建信任所有证书的TrustManager TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }; // 创建SSLContext并使用信任所有证书的TrustManager SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); return new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]) .hostnameVerifier((hostname, session) -> true) // 忽略主机名验证 .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); } catch (Exception e) { throw new RuntimeException(e); } } ``` 然后,在配置文件中启用OKHttp: ```properties feign.okhttp.enabled=true ``` 注意:同样,这种方法仅用于测试环境。 生产环境建议: 在生产环境中,我们应该将目标服务器的证书(或根证书)导入到JVM的信任库中,这样就不需要绕过SSL验证。具体步骤参考之前提供的“导入证书到JVM信任库”。 如果使用Docker容器部署,可以在构建镜像时导入证书。 总结: 在Spring Boot 3.x中配置Feign客户端使用HTTPS,主要在于配置底层的HTTP客户端(如Apache HttpClient或OKHttp)以支持SSL。对于自签名证书,我们可以临时配置信任所有证书,但生产环境应导入证书。 相关问题: 1. 如何在Spring Boot 3.x中为不同的Feign客户端配置不同的SSL设置? 2. 如何在生产环境中为Feign客户端配置双向SSL认证(mTLS)? 3. 如何将SSL证书添加到Spring Boot应用的Docker镜像中?</think>在 Spring Boot 3.x 中配置 Feign 客户端使用 HTTPS 协议,需要解决 SSL 证书验证问题。以下是完整的配置方案,分为开发环境(快速绕过验证)和生产环境(安全配置)两种场景: --- ### 方案一:开发环境(绕过证书验证 - 仅限测试) ```java import feign.Client; import feign.httpclient.ApacheHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.core5.ssl.SSLContextBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.net.ssl.SSLContext; @Configuration public class FeignInsecureConfig { @Bean public Client feignClient() throws Exception { // 创建信任所有证书的SSL上下文 SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, (chain, authType) -> true) // 信任所有证书 .build(); // 配置HTTP客户端 CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)) .build(); return new ApacheHttpClient(httpClient); } } ``` 在 Feign 客户端接口添加配置: ```java @FeignClient( name = "secure-service", url = "https://your-secure-api.com", configuration = FeignInsecureConfig.class // 应用配置 ) public interface SecureServiceClient { @GetMapping("/data") String getSecureData(); } ``` > ⚠️ **警告**:此方案会禁用所有 SSL 验证,仅用于开发测试环境[^1]。 --- ### 方案二:生产环境(安全配置 - 推荐) #### 步骤 1:获取服务器证书 ```bash openssl s_client -connect your-secure-api.com:443 </dev/null | openssl x509 -out api-certificate.crt ``` #### 步骤 2:创建自定义信任库 ```bash # 创建JKS信任库 (密码: changeit) keytool -import -alias api-cert -file api-certificate.crt \ -keystore custom-truststore.jks -storepass changeit ``` #### 步骤 3:Spring Boot 配置 `application.yml`: ```yaml feign: client: config: default: loggerLevel: FULL server: ssl: trust-store: classpath:custom-truststore.jks trust-store-password: changeit ``` #### 步骤 4:创建安全 Feign 配置 ```java import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.core5.ssl.SSLContexts; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import javax.net.ssl.SSLContext; import java.io.InputStream; import java.security.KeyStore; @Configuration public class FeignSecureConfig { @Value("${server.ssl.trust-store}") private Resource trustStore; @Value("${server.ssl.trust-store-password}") private String trustStorePassword; @Bean public CloseableHttpClient httpClient() throws Exception { // 加载信任库 KeyStore truststore = KeyStore.getInstance("JKS"); try (InputStream is = trustStore.getInputStream()) { truststore.load(is, trustStorePassword.toCharArray()); } // 创建SSL上下文 SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(truststore, null) .build(); return HttpClients.custom() .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext)) .build(); } } ``` --- ### 证书验证的数学原理 HTTPS 证书验证基于非对称加密: 1. 服务器证书包含公钥 $K_{pub}$ 和签名 $S$ 2. CA 使用私钥 $K_{priv}$ 生成签名: $$ S = \text{Sign}(K_{priv}, \text{CertData}) $$ 3. 客户端使用 CA 公钥验证: $$ \text{Verify}(K_{pub}^{CA}, \text{CertData}, S) = \text{true} $$ 当客户端信任库中缺少 CA 证书时,验证失败[^2]。 --- ### 最佳实践建议 1. **证书管理**: ```mermaid graph LR A[证书来源] --> B{环境类型} B -->|生产环境| C[公共CA证书] B -->|内部系统| D[私有CA导入信任库] B -->|开发测试| E[临时禁用验证] ``` 2. **证书监控**: ```bash # 检查证书有效期 openssl x509 -in api-certificate.crt -noout -dates # 输出:notBefore=... notAfter=... ``` 3. **容器部署**: ```dockerfile FROM eclipse-temurin:17-jdk COPY target/*.jar app.jar COPY custom-truststore.jks /truststore/ CMD java -Djavax.net.ssl.trustStore=/truststore/custom-truststore.jks \ -Djavax.net.ssl.trustStorePassword=changeit \ -jar app.jar ``` > **重要提示**:生产环境必须使用有效证书,禁用验证会导致中间人攻击风险[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值