Customized Configuration
Spring Boot Project Customization
HTTP Client Customization
WebClient
Applicable to all Spring Boot versions (2.x/3.x/4.x). Supports custom WebClient.Builder to override the default instance.
@Bean
public WebClient.Builder webClientBuilder() {
HttpClient httpClient = HttpClient.create()
.protocol(HttpProtocol.HTTP11)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000)
.responseTimeout(Duration.ofSeconds(30));
return WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.clientConnector(new ReactorClientHttpConnector(httpClient));
}
RestClient
Applicable to Spring Boot 3.2+ and Spring Boot 4.x. Supports custom RestClient.Builder to override the default instance.
@Bean
public RestClient.Builder restClientBuilder() {
return RestClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.requestFactory(new JdkClientHttpRequestFactory());
}
Note: Spring Boot 2.x does not support RestClient, the framework will automatically use WebClient.
JSON Codec Customization
Using Custom JsonMapper (Jackson)
@Bean
public JsonMapper jsonMapper() {
return JacksonJsonMapper.getInstance();
}
Complete Customization Example
@Configuration
public class DifyCustomConfiguration {
@Bean
public WebClient.Builder webClientBuilder() {
HttpClient httpClient = HttpClient.create()
.protocol(HttpProtocol.HTTP11)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000)
.responseTimeout(Duration.ofSeconds(30));
return WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.clientConnector(new ReactorClientHttpConnector(httpClient));
}
@Bean
@ConditionalOnClass(name = "org.springframework.web.client.RestClient")
public RestClient.Builder restClientBuilder() {
return RestClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
}
@Bean
public JsonMapper jsonMapper() {
return JacksonJsonMapper.getInstance();
}
}
Pure Java Project Customization
For pure Java projects, you can customize the configuration through the HttpClientFactory fluent API.
Adding Default Headers
import io.github.guoshiqiufeng.dify.client.integration.okhttp.http.JavaHttpClientFactory;
import io.github.guoshiqiufeng.dify.client.codec.jackson.JacksonJsonMapper;
import io.github.guoshiqiufeng.dify.client.core.http.HttpClientFactory;
// Create base factory
JavaHttpClientFactory baseFactory = new JavaHttpClientFactory(JacksonJsonMapper.getInstance());
// Add default headers
HttpClientFactory customFactory = baseFactory
.defaultHeader("X-Custom-Header", "custom-value")
.defaultHeader("User-Agent", "MyApp/1.0");
// Use custom factory to create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(customFactory)
.build();
Adding Custom Interceptors
import okhttp3.Interceptor;
import okhttp3.Response;
// Create custom interceptor
Interceptor loggingInterceptor = chain -> {
okhttp3.Request request = chain.request();
System.out.println("Request: " + request.url());
Response response = chain.proceed(request);
System.out.println("Response: " + response.code());
return response;
};
// Create factory and add interceptor
HttpClientFactory customFactory = new JavaHttpClientFactory(JacksonJsonMapper.getInstance())
.interceptor(loggingInterceptor);
// Use custom factory to create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(customFactory)
.build();
Configuring Timeouts
Timeouts are configured through ClientConfig:
import io.github.guoshiqiufeng.dify.core.config.DifyProperties;
// Create client configuration
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
clientConfig.setConnectTimeout(60); // Connection timeout 60 seconds
clientConfig.setReadTimeout(60); // Read timeout 60 seconds
clientConfig.setWriteTimeout(60); // Write timeout 60 seconds
clientConfig.setLogging(true); // Enable logging
// Use configuration to create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(new JavaHttpClientFactory(JacksonJsonMapper.getInstance()))
.build();
Performance Optimization Configuration
Connection Pool Configuration
For high-concurrency scenarios, you can configure OkHttp connection pool parameters to improve performance:
import io.github.guoshiqiufeng.dify.core.config.DifyProperties;
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
// Connection pool configuration
clientConfig.setMaxIdleConnections(10); // Max idle connections, default 5 (minimum 1)
clientConfig.setKeepAliveSeconds(300); // Keep-alive duration (seconds), default 300 (minimum 1)
clientConfig.setMaxRequests(128); // Max concurrent requests, default 64 (minimum 1)
clientConfig.setMaxRequestsPerHost(10); // Max concurrent requests per host, default 5 (minimum 1)
clientConfig.setCallTimeout(60); // Call timeout (seconds), 0 means no limit
// SSE timeout configuration
clientConfig.setSseReadTimeout(0); // SSE read timeout (seconds)
// null (default) = use readTimeout
// 0 = disable timeout (for long streaming conversations)
// >0 = use specified timeout
// Create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(new JavaHttpClientFactory(JacksonJsonMapper.getInstance()))
.build();
Configuration Details:
maxIdleConnections: Maximum number of idle connections in the pool, increase for better connection reusekeepAliveSeconds: Keep-alive duration for idle connections, connections exceeding this time will be closedmaxRequests: Global maximum concurrent requests, limits overall concurrencymaxRequestsPerHost: Maximum concurrent requests per host, prevents overwhelming a single servercallTimeout: Total call timeout (including connect, read, write), 0 means no limit
Recommended Settings:
- Low concurrency (< 10 QPS): Use default values
- Medium concurrency (10-100 QPS):
maxIdleConnections=10,maxRequests=128,maxRequestsPerHost=10 - High concurrency (> 100 QPS):
maxIdleConnections=20,maxRequests=256,maxRequestsPerHost=20
SSE Streaming Optimization
For SSE (Server-Sent Events) long-connection scenarios, you can configure specific timeout strategies:
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
// SSE optimization configuration
clientConfig.setSseReadTimeout(0); // Disable SSE read timeout, default 0 (disabled)
// Create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(new JavaHttpClientFactory(JacksonJsonMapper.getInstance()))
.build();
Configuration Details:
sseReadTimeout: Read timeout for SSE streaming responses (seconds)null(default): Use thereadTimeoutvalue0: Completely disable timeout for long-running streaming conversations>0: Use the specified timeout in seconds
Logging Optimization Configuration
For large response scenarios, you can configure logging limits to reduce memory usage:
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
// Logging optimization configuration
clientConfig.setLogging(true); // Enable logging
clientConfig.setLoggingMaskEnabled(true); // Enable log masking, default true
clientConfig.setLogBodyMaxBytes(8192); // Max body bytes in logs, default 4096 (4KB)
clientConfig.setLogBinaryBody(false); // Whether to log binary responses, default false
// Create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(new JavaHttpClientFactory(JacksonJsonMapper.getInstance()))
.build();
Configuration Details:
loggingMaskEnabled: Enable log masking, default true. When enabled, automatically masks sensitive parameters (api_key, token, password, secret, authorization, access_token, refresh_token, etc.)logBodyMaxBytes: Maximum bytes of response body to log, truncated if exceeded. Set to 0 for no limitlogBinaryBody: Whether to log binary responses (e.g., images, files). When enabled, logs binary content size and Content-Type. Recommended to set false to save memory
Recommended Settings:
- Development:
logBodyMaxBytes=0(no limit), convenient for debugging - Testing:
logBodyMaxBytes=8192(8KB), balances readability and performance - Production:
logBodyMaxBytes=4096(4KB) or smaller, reduces memory usage
Complete Performance Optimization Example
import io.github.guoshiqiufeng.dify.core.config.DifyProperties;
import io.github.guoshiqiufeng.dify.client.integration.okhttp.http.JavaHttpClientFactory;
import io.github.guoshiqiufeng.dify.client.codec.jackson.JacksonJsonMapper;
// Create high-performance configuration
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
// Basic timeout configuration
clientConfig.setConnectTimeout(30);
clientConfig.setReadTimeout(30);
clientConfig.setWriteTimeout(30);
// Connection pool optimization (high concurrency scenario)
clientConfig.setMaxIdleConnections(20);
clientConfig.setKeepAliveSeconds(300);
clientConfig.setMaxRequests(256);
clientConfig.setMaxRequestsPerHost(20);
clientConfig.setCallTimeout(60);
// SSE optimization
clientConfig.setSseReadTimeout(0);
// Logging optimization
clientConfig.setLogging(true);
clientConfig.setLoggingMaskEnabled(true);
clientConfig.setLogBodyMaxBytes(4096);
clientConfig.setLogBinaryBody(false);
// Create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(new JavaHttpClientFactory(JacksonJsonMapper.getInstance()))
.build();
Custom JSON Codec
Using Jackson Codec (Default)
import io.github.guoshiqiufeng.dify.client.codec.jackson.JacksonJsonMapper;
// Use default Jackson mapper
JavaHttpClientFactory httpClientFactory = new JavaHttpClientFactory(JacksonJsonMapper.getInstance());
Using Gson Codec
import io.github.guoshiqiufeng.dify.client.codec.gson.GsonJsonMapper;
// Use Gson mapper
JavaHttpClientFactory httpClientFactory = new JavaHttpClientFactory(GsonJsonMapper.getInstance());
Using Jackson 3 Codec (Spring Boot 4.x)
import io.github.guoshiqiufeng.dify.client.codec.jackson3.Jackson3JsonMapper;
// Use Jackson 3 mapper
JavaHttpClientFactory httpClientFactory = new JavaHttpClientFactory(Jackson3JsonMapper.getInstance());
Note: All JSON mappers use the singleton pattern. Use
getInstance()method to get instances. For custom configuration, you can access the underlying instance viagetObjectMapper()orgetGson().
Complete Customization Example
import io.github.guoshiqiufeng.dify.client.integration.okhttp.http.JavaHttpClientFactory;
import io.github.guoshiqiufeng.dify.client.codec.jackson.JacksonJsonMapper;
import io.github.guoshiqiufeng.dify.core.config.DifyProperties;
import io.github.guoshiqiufeng.dify.client.core.http.HttpClientFactory;
import okhttp3.Interceptor;
// 1. Use Jackson mapper
JacksonJsonMapper jsonMapper = JacksonJsonMapper.getInstance();
// 2. Create custom interceptor
Interceptor authInterceptor = chain -> {
okhttp3.Request request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer token")
.build();
return chain.proceed(request);
};
// 3. Create HTTP client factory and configure
HttpClientFactory httpClientFactory = new JavaHttpClientFactory(jsonMapper)
.defaultHeader("X-App-Version", "1.0.0")
.interceptor(authInterceptor);
// 4. Create client configuration
DifyProperties.ClientConfig clientConfig = new DifyProperties.ClientConfig();
clientConfig.setConnectTimeout(60);
clientConfig.setReadTimeout(60);
clientConfig.setWriteTimeout(60);
clientConfig.setLogging(true);
clientConfig.setSkipNull(true);
// 5. Use custom configuration to create client
DifyChatClient client = DifyChatBuilder.builder()
.baseUrl("https://api.dify.ai")
.clientConfig(clientConfig)
.httpClientFactory(httpClientFactory)
.build();
Version Notes
- Spring Boot 2.x: WebClient only
- Spring Boot 3.0-3.1: WebClient only
- Spring Boot 3.2+: WebClient and RestClient supported
- Spring Boot 4.x: WebClient and RestClient supported
- Pure Java Projects: OkHttp client