Spring Ai WebClient、RestClient设置代理

开开心心对接完大模型接口,测试没问题准备下下班时,突然来了个异常:

bash 复制代码
403: Forbidden - {"error":{"message":"This model is not available in your region.","code":403}}

那么恭喜你,又要打怪升级了。

大意是大模型厂商限制你所在的地区调用API。

知道问题解决问题,开干吧。

Spring Ai 支持流式和非流式调用,分别使用RestClient和WebClient调用。核心是给RestClient和WebClient配置代理。

WebClientCustomizer、RestClientCustomizer是Spring提供配置WebClietn和Rest Client的类。

代码:

java 复制代码
@Slf4j
@Configuration
public class HttpClientConfig implements WebClientCustomizer, RestClientCustomizer {
    /**
     * 代理
     */
    @Value("${http.proxy.scheme}")
    private String proxyScheme;
    @Value("${http.proxy.host}")
    private String proxyHost;
    @Value("${http.proxy.port}")
    private Integer proxyPort;

@Override
    public void customize(WebClient.Builder webClientBuilder) {
        ProxySelector proxySelector = new ProxySelector() {
            private final List<Proxy> proxyList = new ArrayList<>();
            {
                // 创建代理对象
                proxyList.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
                proxyList.add(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyHost, proxyPort)));
            }

            @Override
            public List<Proxy> select(URI uri) {
                // 对所有 URL 返回相同的代理
                String host = uri.getHost();
                String scheme = uri.getScheme();
                log.info("select.proxy,host={}", host);
                // 检查是否绕过代理
                if ("localhost".equals(host) || "127.0.0.1".equals(host)) {
                    return List.of(Proxy.NO_PROXY);
                }

                // 可以在这里添加过滤逻辑
                if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
                    return proxyList;
                }

                // 其他协议不使用代理
                return List.of(Proxy.NO_PROXY);
            }

            @Override
            public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
                // 连接失败处理
                log.error("连接到代理失败,address:{},error:{}", sa, ioe.getMessage(), ioe);
            }
        };
        java.net.http.HttpClient httpClient = java.net.http.HttpClient.newBuilder().proxy(proxySelector).build();
        JdkClientHttpConnector connector = new JdkClientHttpConnector(httpClient);
        webClientBuilder.clientConnector(connector);
    }


    @Override
    public void customize(RestClient.Builder restClientBuilder) {
        /*spring ai restClient 配置代理*/
        HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(new HttpHost(proxyScheme, proxyHost, proxyPort));
        HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
        restClientBuilder.requestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }
}
相关推荐
一枕槐安4871 天前
RAG 服务扛住高并发:缓存、队列、限流三件套
java·spring·缓存·异步任务·rag·断路器
YDS8291 天前
Small Spring IOC篇:作用域和FactoryBean
java·后端·spring
雷一言说1 天前
Spring AI 2.0 Modular RAG:接入 Rerank 重排模型
spring
学到老活到老1 天前
第 22 集:Filter、Interceptor、AOP 都能拦截,为什么不能互换?
java·后端·spring
郭小李1 天前
spring 中的 @EnableWebMvc注解和WebMvcConfigurer接口
java·后端·spring
CoderYanger1 天前
Java EE 进阶:5. Spring IoC&DI(第二弹):Spring IoC
java·开发语言·spring boot·spring·面试·职场和发展·java-ee
霸道流氓气质1 天前
AI 翻译插件:翻译记忆级联复用、术语混合检索与结构化质量门禁的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
霸道流氓气质1 天前
智能表单生成器:结构化输出契约、JSON Schema 驱动渲染与 EAV/JSONB 混合存储的 Vue3 + Spring AI 生产级实战
人工智能·spring·json
一缕82年的清风1 天前
谷歌突发王炸:Gemini 4 Carbon 登顶全球第一,大模型三强决战彻底变天
gpt·claude·gemini
java_nnnn1 天前
spring web mvc图书管理小案例
前端·spring·mvc