Forest v1.5.36 版本发布了!此次改动主要支持了 Fastjson2,以及 solon 版本更新
response.getContentLength()
取不到值 (#I90MUX:response.getContentLength() 取不到值,是什么原因?)v2.6.5
v1.5.35
版本发布了!此次版本更新主要实现了后端客户端缓存可配置空间大小以及过期时间
配置缓存大小和过期时间
forest:
backend-client-cache-max-size: 512 # 后端客户端缓存最大空间大小(单位为实例个数,默认为128)
backend-client-cache-expire-time: 3h # 后端客户端缓存超时时间(单位为时间长度,默认为6小时)
v1.5.34
版本发布了!此次更新为解决请求不同的域名很多时,内存消耗越来越大的问题,使用 Caffeine 缓存框架作为后端客户端缓存的缓存
@BaseRequest
或@BaseURL
,在有baseURL属性下,如果方法的完整URL不写端口,就会被baseURL属性的端口覆盖,并不是默认的80端口的bug@Address
还是@BaseRequest
都无法将baseUrl和@Get()
中的url拼接在一起的bug (#I7CAYS:不管是是用@Address还是@BaseRequest都无法将baseUrl和@Get()中的url拼接在一起导致404。使用的forest版本是1.5.31)@Addrees
注解中basePath已/
结尾,方法url不以/
开头,最终地址会出现//
的bug。@DownloadFile
注解在下载文件时的进度日志Forest v1.5.33 发布了,此次版本更新主要支持了 Socks 协议的代理,以及组合注解的属性重写
@Body
注解的数组参数无法正常解析为JSON数组 (#I7UPBR:@Body注解的数组参数无法正常解析为JSON数组)@JSONBody
Collection codes 报错 (#I7QLTS:@JSONBody Collection<String> codes 报错)@SocksProxy
注解@OverrideAttribute
注解Socks 代理的使用方式请看 声明式Socks代理文档 以及 编程式Socks代理文档
组合注解的属性重写请看 文档
v1.5.32 版本发布了!此次版本更新主要修复一些BUG。
@Header
参数中传入 Lazy Lambda 出错 (#I7EIAB:在 @Header 参数中传入 Lazy Lambda 出错)opt: 异步线程池初始化时并发优化
Forest v1.5.31 发布了!该版本是一个小版本发布,主要修复了一些BUG
User-Agent: forest/{version}
的请求头@Address
注解的 schema 属性设置为 https 时报错 (#I6Y6E2:当 @Address 注解的 schema 属性设置为 https 时报错)Forest.VERSION
字段,可动态获取 Forest 版本号v1.5.30
版本发布了,这次版本更新有了较大的改动,支持和适配了 SpringBoot3 和 Solon 框架,将XML模块拆分出了主模块,以及新增了延迟参数特性
项目中新增了forest-spring-boot3-starter
模块,集成时需引入如下的依赖
<!-- Forest 的 SpringBoot3 适配模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot3-starter</artifactId>
<version>1.5.30</version>
</dependency>
<!-- Forest 的 Jakarta XML 支持模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-jakarta-xml</artifactId>
<version>1.5.30</version>
</dependency>
如果是老版本 SpringBoot,依赖方式基本不变,但XML的模块需额外引入
<!-- Forest 对 SpringBoot1或2 的适配模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
<version>1.5.30</version>
</dependency>
<!-- Forest 的 JAXB 支持模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-jaxb</artifactId>
<version>1.5.30</version>
</dependency>
具体做法参考示例项目 https://gitee.com/dromara/forest/tree/master/forest-examples
项目中新增了forest-solon-plugin
模块,集成时需引入如下的依赖
<!-- Forest 的 Solon 适配模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-solon-plugin</artifactId>
<version>1.5.30</version>
</dependency>
<!-- Fastjson、Jackson、Gson 中任选一个JSON框架 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<!-- Forest 的 JAXB 支持模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-jaxb</artifactId>
<version>1.5.30</version>
</dependency>
具体做法参考示例项目 https://gitee.com/dromara/forest/tree/master/forest-examples
本次更新将XML序列化和反序列化相关功能移出了forest-core
主模块,需根据不同的项目情况选择相应的 Forest XML 模块依赖。
如果项目,即普通非 SpringBoot3 项目(Spring、SpringBoot1或2)JDK版本也在17以下的项目,则用forest-jaxb
依赖
<!-- Forest 的 JAXB 支持模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-jaxb</artifactId>
<version>1.5.30</version>
</dependency>
如果您的项目是 SpringBoot3,或是 JDK 17及以上版本的项目,这选择forest-jakarta-xml
依赖
<!-- Forest 的 Jakarta XML 支持模块 -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-jakarta-xml</artifactId>
<version>1.5.30</version>
</dependency>
有很多情况,Header、Query、Body的参数值不能马上得出,而是在请求发送前的那一刻(所有请求参数都到位时)才能得出,典型的例子就是加签验证的场景(在Header中添加一个参数token,而token的值是对整个body做加密的结果)
Forest.post("/test")
.addHeader("Content-Type", "application/json; charset=UTF-8")
// 这里传入的是一个 Lambda 表达式,它会在请求发送的前一刻才执行
// 将会通过对整个请求的Body做序列化后再进行Base64运算得出一个值,并给到Authorization请求头
.addHeader("Authorization", req -> Base64.encode("Token=" + req.body().encodeToString()))
.addBody("id", "1972664191")
.addBody("name", "XieYu20011008")
.execute();
Forest.post("/test")
.addHeader("Content-Type", "application/json; charset=UTF-8")
.addHeader("_id", "20011008")
.addBody("id", "1972664191")
// 这里传入的是一个 Lambda 表达式,它会在请求发送的前一刻才执行
// 执行过程和原理同上
.addBody("name", req -> "Foo" + req.headerValue("_id"))
.addBody("token", req -> Base64.encode(req.body().encode()))
.execute();
这里在延迟参数Lambda表达式中调用的req.body().encode()
执行的body序列化过程,会自动排除
调用它的延迟参数本身,所以不必担心会发生死循环的情况
localhost:8080
这类省略 http:// 的 url特别感谢 Solon 作者 (@noear_admin) 对 Forest 项目在 Solon 适配上的支持
v1.5.28版本发布了,此次版本发布是小版本更新,主要是修复一些BUG,并添加了onBodyEncode
拦截器回调函数
ForestFuture<T>
类型v1.5.27
版本发布了,此次版本发布除了修复一些BUG,另外还支持了 Kotlin 的协程,并且增强了异步请求的API和获取响应数据的API
@Body
参数为空会报错 (#I5Y7WJ:发送 multipart/form-data 请求时,@Body 参数为空会报错 )#
Forest v1.5.26
版本发布了!此次更新主要对一些BUG进行修复
5.3.19
2.6.7
Forest v1.5.25
版本发布了!
Forest v1.5.24 版本发布了!此次版本更新主要解决一些BUG
Forest v1.5.23 版本发布了!此次版本更新对请求执行的性能进行了彻底的优化!
将 OkHttp3 后端的请求 QPS 提升了 3 倍多!
将 Httpclient 后端的请求 QPS 提升了 1 倍多!
@BackendClient
注解进行配置1.5.22
版本发布了!本次更新主要解决了统一连接池问题,并开始支持Kotlin,兼容4.x等较低的spring版本
以前版本的 max-connections
和 max-route-connections
配置属性是针对 OkHttp3 和 HttpClient 后端框架连接池的设置,这样使得不同后端的请求在不同的连接池中,而后端的连接池相互隔离,无法形成统一的最大连接数的限制
而且 OkHttp3 的请求数限制是放在 Dispatcher 中的,而不是在连接池中,而 Dispatcher 直接绑定在了 OkHttpClient 对象上,所以很难对其进行设置和管理,基本上 max-connections
和 max-route-connections
属性对 OkHttp3 是无效的,等于是设置了个寂寞。
而本次更新的统一连接池,可以通过max-connections
和 max-route-connections
属性统一管理 OkHttp 和 HttpClient 所有后端的所有请求的最大请求数和最大每路由请求数,同时也包括异步请求在内可以一同进行限制
新增@Return参数注解,来标识某个参数为返回类型
/**
* 通过 Class 类型参数来标识返回类型
*
* @param clazz 返回类型
* @return clazz 参数所标识的返回类型的实例
* @param <T> 未知泛型参数,通过传入 clazz 参数来明确泛型的实际类型
*/
@Get("/")
<T> T getGenericClass(@Return Class<T> clazz);
/**
* 通过 Type 类型参数来标识返回类型
*
* @param type 返回类型
* @return type 参数所标识的返回类型的实例
* @param <T> 未知泛型参数,通过传入 type 参数来明确泛型的实际类型
*/
@Get("/")
<T> T getGenericType(@Return Type type);
/**
* 通过 TypeReference 类型参数来标识返回类型
*
* @param typeReference 返回类型
* @return typeReference 参数所标识的返回类型的实例
* @param <T> 未知泛型参数,通过传入 typeReference 参数来明确泛型的实际类型
*/
@Get("/")
<T> T getGenericTypeReference(@Return TypeReference<T> typeReference);
本次更新参与贡献的小伙伴
v1.5.21
版本发布了!
此次版本发布主要解决了URL在某些情况下的解析错误问题,以及对字符串模板进行手动URLEncode的支持
v1.5.20
版本发布了,中间因为有其它事情所以停滞了一段时间,还好有其他小伙伴的支持,为此间的版本升级,尤其是JDK 17的兼容做了很多工作,特此感谢。此次版本升级,以支持新版本JDK为主,包括从8到17的所有版本基本都可以兼容(主要测了较为主流的11和17,8不必说,原本就支持)
v1.5.19
版本发布了,此次更新主要修复了一些BUG
fix: 在原生Spring环境中,拦截器无法注入Spring上下文 (#I4UE9T:在原生Spring环境中,拦截器无法注入Spring上下文)
fix: httpclient后端的https连接池并发时数据会串 (#I4TYJ1:httpclient后端的https连接池并发时数据会串)
fix: 响应头两个 Set-Cookie 的时候只能取到最后一个 (#I4TATV: 响应头两个 Set-Cookie 的时候只能取到最后一个)
v1.5.17
版本发布了,本次更新主要修复以往的BUG,以及新增了动态正向代理来源信息的功能
feat: 动态正向代理来源信息 (#I4SYM1:动态正向代理来源信息)
fix: 异常:The file of SSL KeyStore is empty (#I4SYGB:异常:The file of SSL KeyStore is empty)
fix: maxRetryInterval配置失效 (#I4SV2P:maxRetryInterval配置失效)
fix: 主项目没有依赖lang3会报错的问题 (#I4M9DE:主项目没有依赖lang3会报错的问题)
fix: 组合注解未生效 (#I4N2HC:组合注解未生效)
refactor: 去掉 NameUtils 工具类中重复的if分支
1.5.15
版本发布了,本次添加了自定义SSL主机名验证器,以及修复了Response
字符编码和gzip
解压等问题
Forest已参加2021年度OSC中国开源项目评选活动,如果您喜欢Forest或对Forest感兴趣,请投上您宝贵的一票,感谢!
点击投票👉 投票
hostnameVerifier
定义一个实现 HostnameVerifier 接口的类
/**
* 自定义SSL主机名/域名验证器
*/
public class MyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
if ("gitee.com".equals(s)) {
return true;
}
return false;
}
}
将自定义的SSL主机名验证器配置到 Forest 的KeyStore
中
application.yml
文件中配置forest:
ssl-key-stores:
- id: keystore1
hostname-verifier: your.site.MyHostnameVerifier
在接口中绑定
@Post(url = "/something", keyStore = "keystore1")
String postSomething(@Body body);
@SSLHostnameVerifier
注解除了在全局配置文件中的keyStore
中配置外, 也可以通过相关注解直接在接口上绑定
public class MyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
// 只通过域名为 gitee.com 的请求
if ("gitee.com".equals(hostname)) {
return true;
}
return false;
}
}
通过@SSLHostnameVerifier
注解绑定到接口
@Post(url = "/something")
@SSLHostnameVerifier(TrustAnyHostnameVerifier.class)
String postSomething(@Body body);
@SSLSocketFactoryBuilder
注解同理 SSLSocketFactory 也一样可以自定义,同时由@SSLSocketFactoryBuilder
注解来绑定
public class MySSLSocketFactoryBuilder implements SSLSocketFactoryBuilder {
@Override
public SSLSocketFactory getSSLSocketFactory(ForestRequest request, String protocol) throws Exception {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null,
new TrustManager[] { new TrustAllManager() },
new SecureRandom());
System.out.println("do MySSLSocketFactoryBuilder");
return sslContext.getSocketFactory();
}
}
绑定到接口
@Post(url = "/something")
@SSLSocketFactoryBuilder(MySSLSocketFactoryBuilder.class)
String postSomething(@Body body);
本次更新有 @AlexShi 小伙伴参与贡献,万分感谢!
Forest已参加2021年度OSC中国开源项目评选活动,如果您喜欢Forest或对Forest感兴趣,请投上您宝贵的一票,感谢!
点击投票👉 投票
v1.5.14
版本发布!此次版本发布主要解决了异步线程池大小设置问题,以及URL中@
字符解析问题