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配置代理。

WebClientCustomizerRestClientCustomizer是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));
    }
}
相关推荐
Volunteer Technology21 小时前
SpringAI Chat Client (四)
人工智能·spring
ShiJiuD66688899921 小时前
springboot基础篇
java·spring boot·spring
敲敲千反田1 天前
Spring AI
java·人工智能·spring
拽着尾巴的鱼儿1 天前
spring 动态代理
java·后端·spring
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【52】Interrupts 中断机制:案例演示
java·人工智能·spring
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【51】Graph 整体运行全流程
java·人工智能·spring
_waylau1 天前
“Java+AI全栈工程师”问答02:Spring Boot 自动配置原理
java·开发语言·spring boot·后端·spring
Ting-yu1 天前
SpringCloud快速入门(4)---- nacos安装与使用
java·spring·spring cloud
霸道流氓气质1 天前
Spring AI ChatMemory 对话记忆配置JDBC方式到Mysql数据库实战示例与原理讲解
数据库·人工智能·spring
Java面试题总结1 天前
我删掉了项目里 80% 的 try-catch,系统反而更稳了
spring