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));
    }
}
相关推荐
考虑考虑1 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
步行cgn3 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
不会c+3 小时前
Day02 - 需求分析与用例建模
spring
LuTshoes4 小时前
spring ai 实战 手搓 PlaneExecuteAgent
java·人工智能·spring·ai
边境悍匪4 小时前
蜗牛学苑 Java 智能体学习 Day42|项目周开发技术汇总 1 思维导图复盘
java·开发语言·spring boot·学习·spring
4SAPI5 小时前
Gemini 4 Pro 泄露参数解析:2M 上下文时代,企业如何规划 Gemini API 中转与多模型架构?
人工智能·gemini
paopaokaka_luck6 小时前
小学非遗科普平台(AI 非遗科普问答,ECharts学情数据、非遗资源分类与审核,资源收藏下载与学习记录,学习任务发布和作品评分,活动报名签到与统计)
java·人工智能·spring·信息可视化·数据分析·echarts
Yize.6 小时前
Spring Task定时任务全解析:从入门到实战
java·spring
wno7049 小时前
Spring Security添加图形验证码
java·后端·spring
步行cgn12 小时前
Spring Bean 的生命周期详解
java·后端·spring