RestTemplate结合OkHttp3通用Rest Client客户端

本文介绍了如何使用OkHttp3Authenticator进行Basic认证,并探讨了如何将OkHttp3与RestTemplate集成,包括自定义认证、拦截器和Spring RetryTemplate的重试策略。同时涵盖了如何在Spring Boot中配置和使用这些技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<think>好的,我现在需要帮助用户解决在Java中如何接入AI.Dify服务或平台的问题。首先,我要理解用户的需求。用户提到了Dify平台,并且参考了引用中的信息,说明他们可能已经创建了Agent,现在想在其他平台或网站使用,比如通过Java集成。 首先,我需要确认Dify的API文档,看看他们提供的接入方式。根据引用内容,Dify支持通过script、iframe或API接口调用。用户的问题是关于Java的,所以重点在API接口调用上。通常,这类平台的API都是RESTful风格的,使用HTTP请求进行交互。 接下来,我应该考虑如何在Java中发送HTTP请求。常见的做法是使用Java的HttpURLConnection类,或者更高级的库如Apache HttpClientOkHttp,或者Spring的RestTemplate。用户可能需要一个简单的示例,所以选择比较通用的方法,比如使用HttpURLConnection,或者更简洁的OkHttp。 然后,需要了解Dify API的具体要求。比如认证方式,通常是API密钥,放在请求头中。请求体和响应格式可能是JSON。用户需要知道如何构造请求,处理响应。 可能还需要处理异常和错误情况,比如网络问题,认证失败,或者API返回的错误信息。不过,初步的示例可能不需要太复杂的错误处理,但用户在实际应用中需要考虑这些。 另外,用户可能需要知道如何解析返回的数据。比如,如果Dify返回的是JSON格式,可以使用Jackson或Gson库来解析。 现在,我需要组织这些信息,分步骤说明如何在Java中集成Dify的API。首先介绍准备API密钥和端点,然后展示发送POST请求的代码示例,使用不同的HTTP客户端库,并解释每个部分的作用。同时,提醒用户注意异常处理和依赖管理。 最后,生成相关问题,帮助用户进一步了解相关主题,比如认证方式、处理异步响应、使用WebSocket,或者与其他服务比较。</think>在Java中接入Dify.AI服务主要通过其提供的REST API实现,以下是具体实现步骤和代码示例: ### 一、接入准备 1. 获取API凭证 - 登录Dify控制台创建应用后,在「API密钥」页面获取`API_KEY` - 记录API端点地址,格式为:`https://api.dify.ai/v1/{endpoint}`[^1] 2. 添加依赖项 ```xml <!-- JSON处理 --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.9</version> </dependency> <!-- HTTP客户端 --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.9.3</version> </dependency> ``` ### 二、基础API调用实现 ```java import okhttp3.*; public class DifyClient { private static final String API_KEY = "your-api-key"; private static final String API_ENDPOINT = "https://api.dify.ai/v1/completion-messages"; public static String generateText(String prompt) throws IOException { OkHttpClient client = new OkHttpClient(); // 构建JSON请求体 String json = new Gson().toJson(new RequestBody(prompt)); RequestBody body = RequestBody.create(json, MediaType.get("application/json")); Request request = new Request.Builder() .url(API_ENDPOINT) .post(body) .addHeader("Authorization", "Bearer " + API_KEY) .addHeader("Content-Type", "application/json") .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); return response.body().string(); } } static class RequestBody { private final String input; private final String response_mode = "blocking"; private final String user = "java_client"; public RequestBody(String input) { this.input = input; } } } ``` ### 三、高级功能实现 1. 流式响应处理 ```java // 修改请求参数 private final String response_mode = "streaming"; // 处理分块响应 public void streamGenerateText(String prompt, Consumer<String> callback) { // 实现SSE(Server-Sent Events)处理逻辑 // 使用WebSocket或专门的事件流处理器 } ``` 2. 文件上传实现 ```java public String uploadFile(File file) throws IOException { RequestBody fileBody = RequestBody.create(file, MediaType.get("application/octet-stream")); MultipartBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), fileBody) .addFormDataPart("user", "java_client") .build(); Request request = new Request.Builder() .url("https://api.dify.ai/v1/files") .post(body) .addHeader("Authorization", "Bearer " + API_KEY) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } } ``` ### 四、最佳实践建议 1. 建议使用连接池配置 ```java OkHttpClient client = new OkHttpClient.Builder() .connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES)) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(120, TimeUnit.SECONDS) .build(); ``` 2. 建议实现自动重试机制 ```java client = client.newBuilder() .addInterceptor(new RetryInterceptor(3)) .build(); class RetryInterceptor implements Interceptor { private int maxRetries; public Response intercept(Chain chain) throws IOException { // 实现指数退避重试逻辑 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬山境KL攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值