dify-spring-boot-starter
  • Guide
  • Getting-started
  • Install
  • Configure
  • Client Builder
  • Service Status Monitoring
  • Logging Security
  • Features

    • Chat API
    • Workflow API
    • Dataset API
    • Server API
  • Event

    • Instructions
    • Chat event
  • Using configurations
  • Customized Configuration
  • v2.x
  • v1.x
  • v0.x
  • Changelog
  • 简体中文
  • English
GitHub
  • Guide
  • Getting-started
  • Install
  • Configure
  • Client Builder
  • Service Status Monitoring
  • Logging Security
  • Features

    • Chat API
    • Workflow API
    • Dataset API
    • Server API
  • Event

    • Instructions
    • Chat event
  • Using configurations
  • Customized Configuration
  • v2.x
  • v1.x
  • v0.x
  • Changelog
  • 简体中文
  • English
GitHub
  • Config

    • Using configurations
    • Customized Configuration

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 reuse
  • keepAliveSeconds: Keep-alive duration for idle connections, connections exceeding this time will be closed
  • maxRequests: Global maximum concurrent requests, limits overall concurrency
  • maxRequestsPerHost: Maximum concurrent requests per host, prevents overwhelming a single server
  • callTimeout: 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 the readTimeout value
    • 0: 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 limit
  • logBinaryBody: 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 via getObjectMapper() or getGson().

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
Edit this page on GitHub
Last Updated: 2/6/26, 3:37 PM
Prev
Using configurations