`
第三章 OpenFeign默认通讯方式修改成OkHttp,自定义Feign客户端配置详解
在使用OpenFeign时,默认使用的是HTTPURLConnection进行通讯,但我们也可以使用OkHttp替换默认的HTTPURLConnection。下面介绍如何在Spring Boot中配置OpenFeign使用OkHttp进行通讯。
OkHttp是一个非常流行的Java HTTP客户端,由Square公司开发。它可以用来发送HTTP请求和接收HTTP响应,支持HTTP/1.1和HTTP/2协议。OkHttp具有高效、可扩展、易用等特点,可以与各种HTTP服务器进行交互。
OkHttp的主要特点如下:
特点介绍 | |
---|---|
支持HTTP/1.1和HTTP/2协议,并能够自动选择最佳协议版本。 | |
支持连接池和请求重试,可以在不同请求之间共享连接,提高性能。 | |
支持异步和同步请求,可以使用回调、RxJava等方式处理响应。 | |
支持请求和响应拦截器,可以在请求和响应的不同阶段对其进行处理。 | |
支持GZIP压缩和流式上传,可以更高效地传输数据。 | |
提供了丰富的API,可以方便地设置请求头、请求体、超时时间、SSL、代理等参数。 | |
OkHttp被广泛应用于Android和Java平台的开发中,例如在Retrofit、Feign等网络框架中作为底层的HTTP客户端实现。 |
首先,需要在项目中添加OkHttp的依赖,可以在pom.xml文件中添加以下代码:
代码如下(示例):
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.1</version>
</dependency>
创建一个OkHttpClient的实例,并将其注入到OpenFeign的配置中,用于替换默认的HTTPURLConnection。可以在@Configuration标注的配置类中添加以下代码:
@Configuration
public class FeignConfiguration {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
@Bean
public Client feignClient() {
return new OkHttpClient();
}
}
上面的代码中,我们创建了一个OkHttpClient的实例,并将其注入到了OpenFeign的配置中。这样,在使用OpenFeign进行通讯时,就会使用OkHttp进行通讯。
最后,在使用OpenFeign的时候,需要在@FeignClient注解中添加configuration属性,并将其值设置为上面创建的FeignConfiguration类,用于修改OpenFeign的配置,使用我们自定义的OkHttpClient进行通讯。
@FeignClient(name = "user-service", configuration = FeignConfiguration.class)
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
@PostMapping("/users")
User createUser(@RequestBody User user);
}
上面的代码中,我们将configuration属性设置为FeignConfiguration.class,表示使用我们自定义的OpenFeign配置。
FeignConfiguration可以用来自定义Feign客户端的配置,包括修改请求和响应的解析、超时时间、连接池等。
下面是一个简单的示例,展示如何自定义FeignConfiguration。
@Configuration
public class MyFeignConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Decoder feignDecoder() {
final HttpMessageConverter<?> jacksonConverter =
messageConverters.getObject().getConverters().stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.orElseThrow(() -> new IllegalStateException("Unable to find Jackson2 converter."));
return new ResponseEntityDecoder(new SpringDecoder(() -> messageConverters, Collections.singletonList(jacksonConverter)));
}
@Bean
public Encoder feignEncoder() {
final HttpMessageConverter<?> jacksonConverter =
messageConverters.getObject().getConverters().stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.orElseThrow(() -> new IllegalStateException("Unable to find Jackson2 converter."));
return new SpringEncoder(() -> messageConverters, Collections.singletonList(jacksonConverter));
}
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(100, SECONDS.toMillis(1), 5);
}
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
@Bean
public Request.Options feignRequestOptions() {
return new Request.Options(5, SECONDS.toMillis(10));
}
}
上面的代码中,我们自定义了以下内容:
feignDecoder()和feignEncoder():修改请求和响应的解析,使用Jackson2进行序列化和反序列化。
feignRetryer():设置Feign客户端的重试策略,最大重试次数为5次,每次间隔1秒。
feignLoggerLevel():设置Feign客户端的日志级别为BASIC。
feignRequestOptions():设置Feign客户端的连接超时时间为5秒,读取超时时间为10秒。
使用自定义的FeignConfiguration需要在@FeignClient注解中指定configuration属性,例如:
@FeignClient(name = "my-service", url = "${my.service.url}", configuration = MyFeignConfiguration.class)
public interface MyServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
MyResponse findById(@PathVariable("id") Long id);
}
上面的代码中,我们将MyFeignConfiguration.class作为configuration属性的值,用于指定使用我们自定义的Feign配置。
通过自定义FeignConfiguration,我们可以更加灵活地配置Feign客户端,满足不同的需求。
在Spring Boot中,我们可以使用OkHttpClient来自定义OkHttp客户端的配置。
下面是一个示例,展示如何自定义OkHttp客户端的配置:
@Configuration
public class MyOkHttpClientConfiguration {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(30))
.addInterceptor(new LoggingInterceptor())
.build();
}
static class LoggingInterceptor implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long start = System.nanoTime();
LOGGER.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long end = System.nanoTime();
LOGGER.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (end - start) / 1e6d, response.headers()));
return response;
}
}
}
上面的代码中,我们使用@Bean注解来创建一个OkHttpClient的实例,并使用OkHttpClient.Builder来配置它。我们指定了连接超时时间为10秒,读取超时时间为30秒,并添加了一个日志拦截器。
日志拦截器LoggingInterceptor用于在每次请求和响应时打印日志。我们可以在控制台上看到类似如下的日志输出:
Sending request http://example.com/api/foo on HttpConnection{example.com:80, proxy=DIRECT hostAddress=/93.184.216.34:80 cipherSuite=none protocol=http/1.1}
User-Agent: okhttp/3.14.2
Accept: application/json
Host: example.com
Received response for http://example.com/api/foo in 523.9ms
Content-Type: application/json
Content-Length: 32
最后,在我们的Feign客户端接口上使用@Headers注解,来指定使用我们自定义的OkHttp客户端,例如:
@FeignClient(name = "my-service", url = "${my.service.url}", configuration = MyFeignConfiguration.class)
public interface MyServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
@Headers("Content-Type: application/json")
MyResponse findById(@PathVariable("id") Long id);
}
上面的代码中,我们使用@Headers注解来指定请求的Content-Type,并且由于我们在MyOkHttpClientConfiguration中创建了OkHttpClient实例,所以我们自定义的OkHttp客户端会被自动使用。
通过自定义OkHttp客户端配置,我们可以更加灵活地配置Feign客户端的底层网络实现。
通过以上操作,我们就可以在Spring Boot中使用OkHttp替换OpenFeign的默认HTTPURLConnection进行通讯。这样,我们可以更加灵活地配置OpenFeign,满足我们的需求。需要注意的是,使用OkHttp时,需要将其添加到项目的依赖中,并且需要创建OkHttpClient实例,并将其注入到OpenFeign的配置中。