RestTemplate结合OkHttp3通用Rest Client客户端

  • Post author:
  • Post category:其他




RestTemplate结合OkHttp3通用Rest Client客户端



一、OkHttp3 Authenticator认证器(仅支持http响应码401和407)

原理

okhttp3.internal.http.RetryAndFollowUpInterceptor

重试拦截器中,判断http响应码若为{@code 401},则在request请求头附带

Basic认证信息

重新发送请求。

package com.example.request.okhttp3;

import okhttp3.*;

import javax.annotation.Nullable;
import java.io.IOException;

/**
 * <p> 功能描述: Basic 基本认证
 *  注意:http响应码为{@code 401} 时生效,若目标系统自动重定向到登录页面{@code 302}则无法拦截!
 * </p>
 *
 */
public class BasicAuthenticator implements Authenticator {

    private String username;
    private String password;

    public BasicAuthenticator(String username, String password) {
        this.username = username;
        this.password = password;
    }

    /**
     * @see okhttp3.internal.http.RetryAndFollowUpInterceptor
     *
     * @param route
     * @param response
     * @return
     * @throws IOException
     */
    @Nullable
    @Override
    public Request authenticate(@Nullable Route route, Response response) throws IOException {
        String credential = Credentials.basic(this.username, this.password);
        return response.request().newBuilder().header("Authorization", credential).build();
    }

}

        final OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectionPool(pool())
                .connectTimeout(10, TimeUnit.SECONDS)
                .callTimeout(5, TimeUnit.MINUTES)
                .hostnameVerifier((s, sslSession) -> true)
                .authenticator(new BasicAuthenticator("admin","123456"))
                .build();
    /**
     * 连接池
     *
     * @return 连接池
     */
    public ConnectionPool pool() {
        return new ConnectionPool(10, 2, TimeUnit.MINUTES);
    }



二、RestTemplate basicAuthentication

  • 方法1
    /**
     * basic认证
     * {@code RestTemplateBuilder#addClientHttpRequestInitializer(org.springframework.web.client.RestTemplate)}
     */
        restTemplate.getClientHttpRequestInitializers()
                .add(request -> {
                    HttpHeaders headers = request.getHeaders();
                    if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) {
                        headers.setBasicAuth("admin", "123456");
                    }
                });
  • 方法2
        final RestTemplate restTemplate = new RestTemplateBuilder()
                .basicAuthentication("admin", "123456")
                .build();



三、RestTemplate集成OkHttpClient



1.集成OkHttp3

            RestTemplate restTemplate = new RestTemplate();
            final HttpMessageConverters converters = SpringUtil.getBean(HttpMessageConverters.class);
            restTemplate.setMessageConverters(converters.getConverters());
            // 切换类库
            OkHttpClient okHttpClient = okHttp3Client();
            restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory(okHttpClient));
    /**
     * okHttp3Client 客户端
     * {@code https://square.github.io/okhttp/}
     *
     * @return httpClient
     */
    public OkHttpClient okHttp3Client() {
        return new OkHttpClient().newBuilder()
                .connectionPool(pool())
                .connectTimeout(10, TimeUnit.SECONDS)
                .callTimeout(5, TimeUnit.MINUTES)
                .hostnameVerifier((s, sslSession) -> true)
                // 禁止重定向
                .followRedirects(false)
                .build();
    }

    /**
     * 连接池
     *
     * @return 连接池
     */
    public ConnectionPool pool() {
        return new ConnectionPool(10, 2, TimeUnit.MINUTES);
    }



2.自定义OkHttpClient拦截器


okhttp3.Interceptor

    public OkHttpClient okHttp3Client() {
        return new OkHttpClient().newBuilder()
                .addInterceptor(chain -> {
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    if (!response.isSuccessful()) {
                        // 静默关闭
                        closeQuietly(response.body());
                        response = chain.proceed(request);
                    }
                    return response;
                })
                .build();
    }



3.自定义RestTemplate拦截器

RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add((request, body, execution) -> {
                ClientHttpResponse clientHttpResponse = execution.execute(request, body);
                if (clientHttpResponse.getStatusCode().is5xxServerError()) {
                        clientHttpResponse = execution.execute(request, body);
                }
                return clientHttpResponse;
            });



4.集合Spring RetryTemplate框架自动重试


RestTemplate用法-基本认证、JWT Token认证、自动重试

  • pom.xml
      <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
            <version>1.3.1</version>
        </dependency>
  • 重试代码实现
    /**
     * 结合RetryTemplate重试框架(编程式方式)
     * RetryTemplate重试框声明式注解方式:依赖{@code spring-boot-starter-aop }且重试类必须注入为spring bean
     * @param builder
     * @return
     */
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.setConnectTimeout(Duration.ofSeconds(10))
                .setReadTimeout(Duration.ofSeconds(120))
                .additionalInterceptors((request, body, execution) -> {
                    // RetryTemplate 1.3之后支持链式写法
                    RetryTemplate retryTemplate = RetryTemplate.builder()
                            .maxAttempts(10)
                            .exponentialBackoff(100, 2, 10000)
                            .retryOn(RestClientException.class)
                            .build();
                    return retryTemplate.execute(context -> execution.execute(request, body));
                })
                .build();
    }



版权声明:本文为ory001原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。