Q&A
常见问题
# Q: 除了声明式,Forest 支持编程式的请求发送方式吗?
A: 支持,Forest 支持声明式和编程式两种风格的请求发送方式。
编程式发送 GET 请求案例:
// GET 请求访问百度
String baidu = Forest.get("http://www.baidu.com").execute(String.class);
1
2
2
编程式 POST 请求:
// POST 请求
UserVO userVO = Forest.post("http://localhost:{port}/user/create")
.addHeader("Content-Type", "application/json")
.addBody("id", "1972664191")
.addBody("name", "DtFly20011008")
.execute(UserVO.class);
1
2
3
4
5
6
2
3
4
5
6
# Q: 什么是后端?Forest 支持哪些后端?
A: 这里的后端指的是后端HTTP请求框架,Forest 目前支持 Httpclient、OkHttp3 两种后端请求框架。Forest 也支持通过配置更改后端请求框架。
# 在 Spring Boot 项目中的配置
forest:
backend: httpclient # 配置后端框架为 httpclient
1
2
3
2
3
# Q: Forest 支持哪几种 JSON 框架:
A: 支持 Jackson、Gson、Fastjson,从 Forest v1.5.36 版本开始支持 Fastjson2,之前版本只支持 Fastjson 1.x 版本。
# Q: 支持 HTTPS 吗?
A: 支持,分单证和双证两种情况:
- 对于单证,直接访问即可,不需要任何配置。
- 对于双证,需要配置
keystore
或SSLSocketFactory
,详情请参见《HTTPS双证》。
# Q: 支持 Cookie 吗?
A: 支持,详情请参见《声明式 Cookie》和 《编程式 Cookie》
# Q: 支持失败重试吗?
A: 支持,配置maxRetryCount
大于 0 即可,详情请参见《声明式请求重试》和《编程式请求重试》
# Q: 支持 HTTP 代理吗?
A: 支持
- 声明式请求代理
@Post( "http://localhost:8080/hello")
@HTTPProxy(host = "127.0.0.1", port = "10801", username = "root", password = "xxxxxx")
String simplePostWithProxy();
1
2
3
2
3
- 编程式请求代理
Forest.post("http://localhost:8080/hello")
.proxy("http://root@xxxxxx:127.0.0.1:10801")
.execute();
1
2
3
2
3
# Q: 支持 Socks 代理吗?
A: 支持
- 声明式请求 Socks 代理
@Post( "http://localhost:8080/hello")
@SocksProxy(host = "127.0.0.1", port = "10801", username = "root", password = "xxxxxx")
String simplePostWithProxy();
1
2
3
2
3
- 编程式请求 Socks 代理
Forest.post("http://localhost:8080/hello")
.proxy(ForestProxy.socks("127.0.0.1", 10801)
.username("root")
.password("xxxxxx"))
.execute();
1
2
3
4
5
2
3
4
5
详情请参见《声明式请求 Socks 代理》和《编程式请求 Socks 代理》
# Q: 支持负载均衡吗?
A: 不支持,Forest 暂时没有往微服务 RPC 框架发展的想法。但可以通过拦截器或动态根地址等方式来手动实现。
// 实现随机负载均衡策略的 AddressSource 接口
public class MyAddressSource implements AddressSource {
@Override
public ForestAddress getAddress(ForestRequest request) {
// 可以从 Nacos 等注册中心动态获取地址列表
List<ForestAddress> addressList = getRemoteAddressList();
// 随机选出其中一个
Random random = new Random();
int i = random.nextInt(3);
return addressList.get(i);
}
// getRemoteAddressList 方法定义 ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Q: Query 对象的属性支持别名吗?
A: 支持,请参见《对象字段》
# Q: Header 对象的属性支持别名吗?
A: 支持,请参见《对象字段》
# Q: Body 对象的属性支持别名吗?
A: 支持,请参见《对象字段》
# Q: 接受 Response 返回数据的对象属性支持别名吗?
A: 支持,请参见《对象字段》
# Q: Query 对象的属性支持排序吗?
A: 支持,请参见《对象字段》
要完成参数排序需完成以下几个步骤:
- 第一步:确认项目中使用的 JSON 转换器是什么。默认情况下依赖什么 JSON 框架就自动配置为某个 JSON 转换器,如果不能确定,就通过配置明确指定 JSON 转换器:
forest:
converters:
json: # JSON转换器
# JSON转换器设置为Jackson转换器
type: com.dtflys.forest.converter.json.ForestJacksonConverter
1
2
3
4
5
2
3
4
5
更多转换器配置方法请参见《全局转换器配置》
- 第二步:根据项目使用的 JSON 转换器,使用该 JSON 框架的注解来指定参数顺序:
Fastjson:
public class User {
@JSONField(ordinal = 0)
private String name;
@JSONField(ordinal = 1)
private Integer age;
@JSONField(ordinal = 2)
private String job;
...
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Jackson:
public class User {
@JsonProperty(index = 0)
private String name;
@JsonProperty(index = 1)
private Integer age;
@JsonProperty(index = 2)
private String job;
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# Q: Body 对象的属性支持排序吗?
A: 支持,请参见《对象字段》
# Q: Header 对象的属性支持排序吗?
A: 支持,请参见《对象字段》
# Q: 为什么在我的 Spring Boot 项目中,无法注入 Forest 的声明式请求接口?
A:
- 先确认项目中 Spring Boot 的版本,如果是
3.x
,那么就要依赖forest-spring-boot3-starter
;如果是2.x
,就要依赖forest-spring-boot-starter
,搞错 Spring Boot 和 Forest 的对应依赖版本就会出现这种问题。 - 确认 Forest 的声明式接口是否被扫描进 Spring Boot 的上下文中,比如:Forest 接口包名不在 Spring Boot 项目启动类所在的包下面,或者在另一外完全不同包名的子项目中,此时需要在
@ForestScan
注解中指明 Forest 接口所在的包。
# Q: 为什么在我的 Spring Boot 项目中,Forest 的全局配置没有生效?
A:
- 和上面问题一样,先确认 Spring Boot 的版本和 Forest 对应的依赖版本有没有弄错。
- 确认有没有依赖
forest-spring-boot-starter
或forest-spring-boot3-starter
,还是只依赖了forest-core
和forest-spring
- Maven 或 Gradle 依赖中确实有
forest-spring-boot-starter
或forest-spring-boot3-starter
, 但实际的项目依赖中确没有(可能是没有 Maven reload,或是依赖错误)。建议使用 Idea 的 Maven Helper 来查 Maven 依赖问题。 - 确认注入 Forest 接口的类是否在 Spring 上下文中,比如:这个类不是通过 Spring 机制产生的 Bean,而是自己手动 new 出来的 Java 对象,或是这个类不在 Spring 的扫描范围内。
# Q: 为什么自定义的 Forest 拦截器中无法注入 Spring 上下文中的 Bean
A:
- 和以上问题一样,先确认 Spring Boot 的版本和 Forest 对应的依赖版本有没有弄错。
- 确认该拦截器类是否挂上了
@Component
注解,没有挂该注解就无法被自动扫描到 Spring 上下文,需要通过 Spring Boot 配置类的@Bean
方法等方式来手动定义该拦截器为 Spring 上下文中的 Bean。 - 确认该拦截器类所在包名是否不在 Spring Boot 项目启动类所在的包下面以至于该类没被扫描进 Spring 上下文中。
- 确认在该拦截器中要注入的 Bean 是否在 Spring 上下文中,比如:这个 Bean 不是通过 Spring 机制产生的,而是自己手动 new 出来的 Java 对象,或是这个 Bean 不在 Spring 的扫描范围内。
# Q: 遇到 404、500 等网络错误如何调试?
A:
- 400、404 等错误都是请求端的错误,即发送到服务端的请求内容不合法直接被服务端拒绝了。
- 500、502 等错误都是服务端的错误,此时服务端已经接受到了客户端发送的请求,但在服务端内部处理该请求的时候发生了错误。
- 不管是 4xx 还是 5xx 错误,都极有可能是请求的参数不符合服务端程序要求所导致的。所以必须先确认发送的请求的内容是否是符合要求的,这时需要查看 Forest 请求日志,以及在 Postman 等HTTP抓包工具中调试。
# Q: 如何结合 Postman 来调试网络问题?
A:
- 第一步:在 Postman 中输入完整的、符合要求的请求类型、URL、Query、Body、Header 等必要的参数。然后点击发送。
- 第二步:在 Postman 窗口左下角,找到 Console 选项卡,点击即可看到 Postman 的控制台。
- 第三步:在 Console 中,找到之前 HTTP 请求发送的历史记录,然后点击展开,可以看到请求抓包的具体内容,包括了 Header、Body 等所有具体 HTTP 信息。
- 第四步:对比 Postman 控制台中的成功的请求信息和 Forest 错误请求的请求日志中的所有参数,找出它们中不一致的地方。
帮助我们改善此文档 (opens new window)
上次更新: 2024/06/06, 01:20:23