Forest Forest
首页
  • 当前版本

    • v1.6.x
  • 历史版本

    • v1.5.36
    • v1.5.35
    • v1.5.33
    • v1.5.30 ~ v1.5.32
    • v1.5.0 ~ v1.5.28
  • 插件

    • ForestX
  • 问答

    • 常见问题
    • 更新记录
案例
  • 加入群聊
  • 赞助我们
  • 参与贡献
  • 贡献者们
  • 项目介绍
  • 开发团队
  • 关于作者
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Fast Request - IDEA版Postman,为简化API调试而生 (opens new window)
  • Bean Searcher - 专注高级查询的只读 ORM (opens new window)
  • zyplayer-doc - 可私有化部署的文档与知识库管理平台 (opens new window)
  • frSimple - 中后台脚手架/小程序商城 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
  • GitCode (opens new window)
首页
  • 当前版本

    • v1.6.x
  • 历史版本

    • v1.5.36
    • v1.5.35
    • v1.5.33
    • v1.5.30 ~ v1.5.32
    • v1.5.0 ~ v1.5.28
  • 插件

    • ForestX
  • 问答

    • 常见问题
    • 更新记录
案例
  • 加入群聊
  • 赞助我们
  • 参与贡献
  • 贡献者们
  • 项目介绍
  • 开发团队
  • 关于作者
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Fast Request - IDEA版Postman,为简化API调试而生 (opens new window)
  • Bean Searcher - 专注高级查询的只读 ORM (opens new window)
  • zyplayer-doc - 可私有化部署的文档与知识库管理平台 (opens new window)
  • frSimple - 中后台脚手架/小程序商城 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
  • GitCode (opens new window)
  • 入门

    • 🎬 安装配置说明
    • 🏹 Springboot环境安装
    • 📐 Springboot环境配置
    • 🎯 Springboot环境使用
    • 🏹 Springboot3环境安装
    • 📐 Springboot3环境配置
    • 🎯 Springboot3环境使用
    • 🏹 Spring环境安装
    • 📐 Spring环境配置
    • 🎯 Spring环境使用
    • 🏹 Solon环境安装
    • 📐 Solon环境配置
    • 🎯 Solon环境使用
    • 🏹 原生Java环境安装
    • 📐 原生Java环境配置
    • 🎯 原生Java环境使用
    • 🧬 编程式接口
  • 配置项

    • 👜 Springboot环境配置项
    • 👝 Spring环境配置项
    • 👜 Solon环境配置项
    • 🎒 原生Java环境配置项
    • 📚 配置优先级/作用域
  • 声明式接口

    • 🧱 构建接口
    • 🍀 请求方法
    • 🚚 请求地址
    • 🎈 URL 参数
    • 🍭 请求头
    • 👔 请求体
    • 🍮 后端框架
    • 🧁 接口注解
    • 📬 接收数据
    • 🍛 数据转换
    • 🎀 对象字段
    • 🍓 成功/失败条件
    • 🍌 重试机制
    • 🥂 重定向
    • 🍔 Gzip解压
    • 🎂 日志管理
    • ⚽ 回调函数
    • 🍟 异步请求
    • 🛡️ HTTPS
    • 🍪 使用Cookie
    • 🛸 使用代理
      • 🍉 上传下载
      • 🚑 异常处理
    • 编程式接口

      • 请求API

        • 🚀 请求对象
        • 🚢 请求属性
        • ✨ 执行请求
        • 🎊 后端框架
        • 🎪 请求类型
        • 🔮 请求地址
        • 🧀 URL 参数
        • 🚅 请求头
        • 🚋 请求体
        • ⚓ 回调函数
        • 🚁 异步请求
        • 🥯 Cookie
        • 🍜 成功/失败条件
        • 🌶️ 重试机制
        • ⛵ 重定向
        • 🛰️ 请求代理
      • 响应API

        • 🌠 响应对象
        • ✒️ 读取数据
        • 🦋 响应状态码
        • 🏥 响应错误处理
        • 🎧 响应头
        • 🥞 Cookie
    • 模板表达式

      • 🍬 Hello World
      • 🍹 配置属性引用
      • 🍖 变量引用
      • 🥃 动态变量绑定
      • 🥗 参数序号引用
      • 🍍 引用对象属性
      • 🥝 调用对象方法
    • 高级特性

      • 🥪 拦截器
      • 🍏 自定义注解
      • 🍇 组合注解
      • 🥑 自定义转换器
    • v1.5.36文档
    • 声明式接口
    公子骏
    2022-07-01
    目录

    🛸 使用代理

    众所周知,我们平时访问HTTP,就是直接输入URL外加Query参数或Body参数就开始直接发送请求,随后等待服务端响应便可。请求通过内网或公网一般都可以正常工作(如果客户端和服务端设备正常联通网络的话),就如下图所示:

    proxy

    # 正向代理

    但也有很多服务由于网络限制等诸多原因,无法直接访问到。这时候就需要先连接代理服务器,然后再由代理服务器转发请求到您原本要访问的原始服务器。 这种方式,便称为正向代理,过程如下图所示:

    proxy

    当然,正向代理除了能访问原本访问不到的资源这一功能外,还有其它用处:

    • 访问原来无法访问的资源,如: Google、油管、企业私有网络服务等
    • 做缓存,加速访问速度
    • 对客户端访问授权和认证
    • 记录用户访问记录(上网行为管理)

    除了有正向代理外,自然也有反向代理,但这个概念不在本文档讨论范围,有兴趣可以自行搜索查询相关资料。

    # HTTP代理

    Forest从1.5.0-RC1版本开始支持HTTP协议的正向代理,通过声明式的注解即可完成相关任务

    使用@HTTPProxy注解便可以非常简单地为某一个请求方法设置代理,该注解有以下几个属性:

    • host: 代理服务器主机地址

    • port: 代理服务器端口号

    • username: 代理服务验证的用户名

    • password: 代理服务验证的密码

    /**
     * 使用 @HTTPProxy 注解设置代理服务器
     * host属性为代理服务器主机地址
     * port属性为代理服务器端口号
     */
    @Post( "http://localhost:8080/hello")
    @HTTPProxy(host = "127.0.0.1", port = "10801")
    String simplePostWithProxy();
    
    /**
     * 使用 @HTTPProxy 注解设置带密码验证的代理服务器
     * host属性为代理服务器主机地址
     * port属性为代理服务器端口号
     * username属性为代理服务验证的用户名
     * password属性为代理服务验证的密码
     */
    @Post("http://localhost:8080/hello")
    @HTTPProxy(host = "127.0.0.1", port = "10801", username = "root", password = "xxxxxx")
    String simplePostWithProxyAuth();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    @HTTPProxy注解也可以设置在接口类上,批量给接口中所有方法设置相同的代理服务器

    /**
     * 为 PostClient 接口中所有的请发方法设置代理服务器
     */
    @BaseRequest(baseURL = "http://localhost:8080")
    @HTTPProxy(host = "127.0.0.1", port = "10801")
    public interface PostClient {
        
        ... ...
    
    }
    
    
    /**
     * 为 PostClientWithProxyAuth 接口中所有的请发方法设置带密码验证的代理服务器
     */
    @BaseRequest(baseURL = "http://localhost:8080")
    @HTTPProxy(host = "127.0.0.1", port = "10801", username = "root", password = "xxxxxx")
    public interface PostClientWithProxyAuth {
        
        ... ...
    
    }
    
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    # Socks代理

    Forest 从v1.5.33版本开始支持 Socks 协议的正向代理,使用方式也基本和 HTTP 代理一致

    通过@SocksProxy注解便可以非常简单地为某一个请求方法设置代理,该注解有以下几个属性:

    • host: 代理服务器主机地址

    • port: 代理服务器端口号

    • username: 代理服务验证的用户名

    • password: 代理服务验证的密码

    /**
     * 使用 @SocksProxy 注解设置 Socks 协议代理服务器
     * host属性为代理服务器主机地址
     * port属性为代理服务器端口号
     */
    @Post("http://localhost:8080/hello")
    @SocksProxy(host = "127.0.0.1", port = "1089")
    String simplePostWithSocksProxy();
    
    
    /**
     * 使用 @SocksProxy 注解设置带密码验证的 Socks 协议代理服务器
     * host属性为代理服务器主机地址
     * port属性为代理服务器端口号
     * username属性为代理服务验证的用户名
     * password属性为代理服务验证的密码
     */
    @Post(
            url = "http://localhost:8080/hello",
            data = "username=foo&password=123456"
    )
    @SocksProxy(host = "127.0.0.1", port = "1089", username = "root", password = "xxxxxx")
    String simplePostWithSocksProxyAndAuth();
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    @SocksProxy注解同样也可以设置在接口类上

    /**
     * 为 PostClient 接口中所有的请发方法设置代理服务器
     */
    @BaseRequest(baseURL = "http://localhost:8080")
    @SocksProxy(host = "127.0.0.1", port = "10801")
    public interface PostClient {
        
        ... ...
    
    }
    
    
    /**
     * 为 PostClientWithProxyAuth 接口中所有的请发方法设置带密码验证的代理服务器
     */
    @BaseRequest(baseURL = "http://localhost:8080")
    @SocksProxy(host = "127.0.0.1", port = "10801", username = "root", password = "xxxxxx")
    public interface PostClientWithProxyAuth {
        
        ... ...
    
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    @HTTPProxy注解也可以用于声明 Socks 协议的代理,只要设置 type 属性为ForestProxyType.Socks

    /**
     * 使用 @HTTPProxy 注解也可以设置 Socks 协议的代理服务器
     * type属性为正向代理的协议类型,有 HTTP 和 Socks 两个枚举值
     * host属性为代理服务器主机地址
     * port属性为代理服务器端口号
     */
    @Post( "http://localhost:8080/hello")
    @HTTPProxy(type = ForestProxyType.Socks, host = "127.0.0.1", port = "10801")
    String simplePostWithProxy();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # 动态传参

    Forest 提供了三种方式来实现动态的代理传参,能够让你在发送请求的那一刻零时决定代理的地址、端口号等参数

    动态正向代理传参的三个方式:1. 显示传参;2. 隐式传参;3. 拦截器传参

    # 显示传参

    使用字符串模板,可以地将全局变量或参数动态传入代理中,也称为(显示)动态正向代理传参

    关于如何使用字符串模板以及变量的配置,请参见《模板表达式》

    
    /**
     * 使用 @HTTPProxy 注解设置代 HTTP 协议的理服务器
     * host 属性值来自全局变量 proxy.host
     * port 属性值来自全局变量 proxy.port
     * username 属性值来自方法的第一个参数 uname
     * password 属性值来自方法的第二个参数 pass
     */
    @Post( "http://localhost:8080/hello")
    @HTTPProxy(host = "{proxy.host}", port = "{proxy.port}", username="{0}", passowrd="{1}")
    String simplePostWithHTTPProxy(String uname, String pass);
    
    /**
     * 使用 @SocksProxy 注解设置代 Socks 协议的理服务器
     * host 属性值来自全局变量 proxy.host
     * port 属性值来自全局变量 proxy.port
     * username 属性值来自方法的第一个参数 uname
     * password 属性值来自方法的第二个参数 pass
     */
    @Post( "http://localhost:8080/hello")
    @SocksProxy(host = "{proxy.host}", port = "{proxy.port}", username="{0}", passowrd="{1}")
    String simplePostWithSocksProxy(String uname, String pass);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    # 隐式传参

    如果不想在@HTTPProxy或@SocksProxy中显式声明主机地址等信息,并且需要根据请求的各项信息来进行复杂的逻辑判断后才能决定正向代理的具体属性值,那么就可以通过以下方式来实现(隐式)动态正向代理

    定义一个类,实现com.dtflys.forest.callback.HTTPProxySource接口

    /**
     * 自定义正向代理来源
     */
    public class MyHTTPProxySource implements HTTPProxySource {
    
        @Override
        public ForestProxy getProxy(ForestRequest req) {
            // req 为 Forest 请求对象
            
            String host = "Your Proxy Host"; // 获取代理服务地址
            Integer port = ...; // 获取代理服务端口
            ForestProxyType type = ...; // HTTP 或 Socks
            // ForestProxyType 是一个枚举类,它有两个枚举值:
            // ForestProxyType.HTTP: 代表 HTTP 协议的代理类型
            // ForestProxyType.Socks: 代表 Socks 协议的代理类型
            
            String username = "Your Proxy Username"; // 代理服务验证的用户名
            String password = "Your Proxy Password"; // 代理服务验证的密码
            return new ForestProxy(type, host, port)
                    .username(username)
                    .password(password);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    通过@HTTPProxy注解的source属性配置自定义的正向代理来源

    /**
     * 使用 @HTTPProxy 注解设置代理服务器
     * 它可以可以是 HTTP 协议,也可以是 Socks 协议
     * 取决于 MyHTTPProxySource 中返回的 ForestProxy 对象的 type 属性
     */
    @Post( "http://localhost:8080/hello")
    @HTTPProxy(source = MyHTTPProxySource.class)
    String simplePostWithHTTPProxy(String uname, String pass);
    
    1
    2
    3
    4
    5
    6
    7
    8

    # 拦截器传参

    在拦截器中构建 ForestProxy 对象实例,并赋值给 Forest 请求对象的 proxy 属性

    关于如何使用和配置拦截器,请参见《拦截器》

    
    class MyHTTPProxyInterceptor implements Interceptor {
    
        @Override
        public boolean beforeExecute(ForestRequest req) {
            String host = "Your Proxy Host"; // 获取代理服务地址
            Integer port = ...; // 获取代理服务端口
            String username = "Your Proxy Username"; // 代理服务验证的用户名
            String password = "Your Proxy Password"; // 代理服务验证的密码 
            
            // 使用 ForestProxy.http 方法构建基于 HTTP 协议的 Forest 正向代理对象
            req.proxy(ForestProxy.http(host, port)
                    .username(username)
                    .password(password));
            
            // 或者使用 ForestProxy.socks 方法构建基于 Socks 协议的 Forest 正向代理对象
            req.proxy(ForestProxy.socks(host, port)
                    .username(username)
                    .password(password));
            return true;
        }
        
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    帮助我们改善此文档 (opens new window)
    上次更新: 2024/12/26, 12:59:11
    🍪 使用Cookie
    🍉 上传下载

    ← 🍪 使用Cookie 🍉 上传下载→

    Theme by Vdoing | Copyright © 2016-2025 公子骏 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式