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));
    }
}
相关推荐
代码什么用9 小时前
Spring基础使用
java·后端·spring
代码什么用9 小时前
Spring对IoC的实现
数据库·spring
Su米苏9 小时前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
java资料站12 小时前
二、Spring AI Alibaba · ChatModel
java·windows·spring
java资料站13 小时前
五、Spring AI Alibaba · Memory · Saver(短期会话)
java·spring·microsoft
deepseek2317 小时前
Gemini 4 Argon拆解:单次输出100万Token不是上下文游戏,长周期Agent的经济账怎么算
大模型·llm·谷歌·ai agent·gemini
bst@微胖子18 小时前
Spring AI (5) : MCP 深度实战:从工具抽取到鉴权,SSE 与 STDIO
人工智能·spring·dubbo
Nebula_g18 小时前
JavaSE拓展:工具类Executors
java·开发语言·后端·spring·基础·javase
鱼宵19 小时前
Spring AI 可观测与透明化:traceId 串起全链路,思考过程实时直播给用户
java·人工智能·spring·链路追踪·springai
Raas10019 小时前
AI网关能做语义缓存吗?MAI Gateway(魔芋企业级AI网关)实战能力深度解读
java·后端·spring