Releases: dromara/forest
v1.8.0
Forest v1.8.0 版本发布了,此次版本升级主要支持了响应式接口,声明式接口和编程式接口都能支持将 Flux 和 Mono 作为响应返回类型。
支持响应式
在使用响应式特性钱,需要先新增以下 Maven 依赖
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-reactor</artifactId>
<version>1.8.0</version>
</dependency>新版本 Forest 支持在声明式接口中,使用 Flux 或 Mono 作为响应数据的返回类型
public interface ReactorClient {
// 支持 Flux 作为返回类型
@Get("/flux")
Flux<String> testFlux();
// 支持 Mono 作为返回类型
@Get("/mono")
Mono<String> testMono();
}支持 SSE 转 Flux
Forest.get("/sse")
.sse(ReactorSSE.class) // 使用 ReactorSSE 类
.setOnMessage((event, sink) -> {
String data = event.value(String.class);
sink.next("data: " + data); // 发布消息
})
.toFlux(String.class) // 转化为 Flux<String> 类型
.subscribe(name -> {
// 订阅消息
System.out.println("value -> " + name);
});新增特性
- feat: 支持 Flux 作为响应返回类型
- feat: 支持 Mono 作为响应返回类型
- feat: 支持 SSE 转 Flux
修复问题
- fix: SSE 在 AUTO 模式下无法识别某些字符串格式的问题
v1.7.6
Forest v1.7.6 版本发布了,此次发布解决了一些Bug,并优化了一些性能。
性能优化
将一些每次请求都要做的操作放到了初始化阶段一次做完,优化了一些性能。实测在 httpclient 作为后端的情况下,可以达到和 hutool HttpUtil 一样的性能,某些场景下(编程模式下手动关闭响应的请求)甚至有所超过。
修复问题
- fix: 当 httpclient 做后端的时候,响应会拿不到带泛型的数据 (#243)
- fix: x-www-form-urlencoded 格式的 body 字符串未按标准的形式进行转义
- fix: 后端为 okhttp3 时,并且 Content-Type 中
; charset=部分带空格的话,实际发送的和设置的不一致
优化内容
- opt: 优化请求性能
v1.7.5
Forest v1.7.5 版本发布了,此次发布主要解决了一些Bug。
修复问题
- fix: 使用
@BaseRequest的baseURL指定域名失效
v1.7.4
Forest v1.7.4 版本发布了!此次版本发布主要支持了在编程式接口中使用和修改字符串模板变量
编程式接口中的模板变量
可以在URL中使用模板变量
Forest.get("{baseURL}/test/{myPath}");可以在请求头中使用模板变量
Forest.post("/test")
.addHeader("Content-Type", "{myContentType}")
.addHeader("name", "{myName}");可以在字符串型请求体中使用模板变量
Forest.post("/test")
.contentTypeJson()
.addBody("{myBody}");可以在 K-V 型请求体中使用模板变量
Forest.post("/test")
.contentFormUrlEncoded()
.addBody("a", "{a}")
.addBody("b", "{b}");其他可以使用模板变量的编程式接口
Forest.get("/")
.host("{myHost}") // host
.port("{myPort}") // port
.path("{myPath}") // path
.charset("{myCharset}") // charset
.connectTimeout("{myConnTimeout}") // connect timeout
.readTimeout("{myReadTimeout}"); // read timeout新特性
- feat: 在编程式接口中,在
ForestRequest对象中新增var(name, value)、var(name)、varAs(name, class)方法,用于修改和获取请求级别的变量 - feat: 在编程式接口中,
url、header、Key-Value形式的body支持使用字符串模板 - feat: 在编程式接口中,
connectTimeout方法和readTimeout方法支持接受字符串模板作为参数 - feat: 在编程式接口中,
charset方法支持接受字符串模板作为参数 - feat: OAuth2 增加
OAuth2#forestInterceptor属性,可以增加自定义拦截器来对获取 Token 的请求进行一些操作
修复问题
- fix: 默认不对cookie的值进行编码和反编码(#ICVPUG)
v1.7.3
Forest v1.7.3 版本发布了!任然是 Bug Fix,继续升级即可。
修复错误
- feat: 新增 Forest 请求的 logRequestHeaders、logRequestBody 日志开关配置
- fix: 重复读取响应流时报错
- fix: 嵌套json字符串无法正常解析
v1.7.2
Forest v1.7.2 版本发布了!这个版本就是些 Bug Fix,没什么好说的,无脑升级即可。
修复错误
- fix: 调用声名式接口的 hashCode() 方法会死循环
- fix: 以 ForestResponse 为返回类型时,T 的子类匹配问题
v1.7.1
Forest v1.7.1 版本发布了!本次发布包含了很多重大更新内容,我们对字符串模板的语法进行了增强,支持了空安全语法和深度变量引用,并提供了更友好的报错信息;在Cookie方面也进行了增强,提供了Cookie自动保存和读取的机制,并添加了更完善的API接口;我们也对拦截器进行了优化改进,不再建议直接使用Interceptor接口和它的onSuccess方法,取而代之的是ForestInterceptor和onResponse方法,它们要比前者更安全,性能也更好;除此之外,此次更新对请求的性能进行了全面的优化,在默认使用编程式接口、不打印日志的情况下,可以达到和 hutool 的 HttpUtil 差不多的耗时。
空安全语法
在原来版本,如果在字符串模板中引用一个没定义过的变量会支持报错。现在用空安全语法可以让它不再报错,而是直接返回 null 值。
// 没定义过 testVar 变量,通过 ? 一样可以正常引用
Forest.get("/test/{testVar?}");或者,引用了一个不存在或值为 null 的变量后,再用点.访问它的属性,这在老版本中自然是直接报错的。现在,可以通过?.符号自动判断是否为空。
// 会先判断 testVar 是否为空,然后 testVar.a 是否为空,其中一个为空就会直接返回 null
// 不会报错
Forest.get("/test/{testVar?.a?.name}");深度引用
在原来版本中,字符串模板中的变量只能引用到第一层,如果该变量的值是引用其他的变量,字符串模板并不会进行解析。而现在,不管引用了多少层变量,都可以解析到底。
forest:
variables:
var1: "{user.name}"
var2: "{user.password}"
user:
name: foo
password: bar在Java代码中直接引用
// 最终 URL 为: /test/foo/bar
Forest.get("/test/{var1}/{var2}");如果不想进行深度引用,可以使用深度引用停止语法,即在变量后加上!符号,那么就只会引用一层该变量的值,至于该变量的值是否会包含其他字符串模板的内容,就不会再进行解析了。
// 最终 URL 为: /test/{user.name}/{user.password}
// 变量 var1 和 var2 的值直接返回字符串,而不会进行任何解析
Forest.get("/test/{var1!}/{var2!}");更安全的拦截器
本次版本更新后,不再建议使用Interceptor(当然要用也可以用,不影响以前的老代码),同时引入了更安全的ForestInterceptor接口
public class MyInterceptor implements ForestInterceptor {
@Override
public ResponseResult onResponse(ForestRequest request, ForestResponse response) {
if (response.isError()) {
// 返回错误标志
return error(response.getException());
}
// 通过 response.getResult() 或 response.get(数据类型.class) 来获取响应数据
// 返回继续执行标志
return proceed();
}
}请求级别日志开关
不再需要 new 一个 LogConfiguration 对象,直接在 ForestRequest 的链式调用中即可设置日志开关
Forest.post("/test")
.logEnabled(true) // 请求日志总开关
.logRequest(true) // 请求内容日志开关
.logResponseStatus(true) // 响应状态日志开关
.logResponseHeaders(true) // 响应头日志开关
.logResponseContent(false) // 响应体内容日志开关
.execute();新增特性
- feat: 字符串模板支持空安全语法
- feat: 更友好的字符串模板错误消息
- feat: 字符串模板
{、${等符号支持转义\\{、\\${ - feat: 字符串模板支持深度变量引用
- feat: 字符串模板支持停止深度引用的语法
- feat: 支持嵌套字符串模板
- feat: 新增更安全的 Forest 拦截器接口 ForestInterceptor
- feat: 通过配置自定义异步线程池拒绝策略
- feat: 支持Bear 认证器
- feat: 支持
@Var作为方法和类的变量绑定注解 - feat: 新增 ForestRequest 级别的日志开关接口
- feat: 增强 Cookie 相关 API 接口
- feat: 后台自动清理过期 Cookie
- feat: 支持 Cookie 自动化存取机制
修复错误
- fix: 和老版本forest冲突时,新版本Forest类缺乏get(url)、post(url)等方法签名,造成错误 (#IC7LIH)
- fix: body log在部分环境中文乱码
- fix: 修改接口中常量的命名,避免用户在其与只有大小写区别的方法之间产生混淆
重构内容
- refactor: 重构URL解析过程
- refactor: 重构变量作用域
- refactor: 重构 Forest 变量体系
- refactor: ForestCookie 不再依赖 OkHttp
- refactor: ForestCookie.parse() 接口
- refactor: 添加键值对类型请求体删除接口 ForestBody.removeNameValueBody
代码优化
- optimize: 优化请求性能
- optimize: 根据 Response 类型动态判断响应是否自动关闭
- optimize: 默认后端改为 httpclient
- optimize: 拦截器优化
v1.6.4
Forest v1.6.3 版本发布了!此次版本更新主要调整了 SSE 消息处理方面的接口
SSE 消息行模式
SSE 的消息通常为标准的多行一组的name:value格式,每组消息用空白行隔开,具体如下:
id:1
event:json
data:{"name":"a"}
text:xxx
id:2
event:json
data:{"name":"b"}
text:yyy
对于这种标准的格式,可使用多行(MULTI_LINES),或自动(AUTO)模式
Forest.get("/sse")
.sse()
.setOnMessage(event -> {
event.id(); // 消息名为 id 的值,这里应得到 1, 2
event.event(); // json
event.data(); // {"name": "a"}, ...
event.value("text"); // 获取非标准名称的消息值,如: text,这里应得到 xxx, yyy
})
.listen(SSELinesMode.MULTI_LINES);或者使用AUTO,listen方法不传参数的情况下,默认为AUTO,AUTO模式会自动识别需要采用的行模式
// AUTO 模式会自动识别需要采用的行模式
sse.listen(); // 默认行模式为 AUTOSSE 的消息除了有标准格式,还有很多非标准的格式,比如每行都是一条JSON字符串,每一行都是单独的消息
{"name":"a"}
{"name":"b"}
{"name":"c"}
对于这种类型的消息,就要使用单行模式(SINGLE_LINE)
Forest.get("/sse")
.sse()
.setOnMessage(event -> {
String str = event.value(); // 获取字符串类型的消息值
MyUser user = event.value(MyUser.class); // 获取消息值并转换为自定义类型
})
.listen(SSELinesMode.SINGLE_LINE);新增特性
- feat: 添加根据类型获取body对象的接口,可通过
request.body().get(Class)获得body中对应类型的对象 - feat: 支持指定 SSE 消息行模式,包括单行、多行、以及自动模式
修复问题
- fix: 由Content-Type中
; charest=utf8部分包含空格导致的body无故乱码的问题 - fix: 和老版本forest冲突时,新版本Forest类缺乏get(url)、post(url)等方法签名,造成错误
v1.6.3
Forest v1.6.3 版本发布了!此次版本更新主要调整了 SSE 相关的API接口,以及更新了maven依赖
新增特性
- add: EventSource.value(Class) 方法
- add: EventSource.value(TypeReference) 方法
不兼容改动
- refactor: SSEInterceptor.onSSEClose(ForestRequest, ForestResponse) 方法参数改为 SSEInterceptor.onSSEClose(EventSource)
- refactor: ForestSSE.setOnClose(BiConsumer<ForestRequest, ForestResponse>) 方法参数改为 ForestSSE.setOnClose(Consumer)
- refactor: EventSource.getValue() 方法重命名为 EventSource.value()
- refactor: EventSource.getName() 方法重命名为 EventSource.name()
- refactor: EventSource.getRawData() 方法重命名为 EventSource.rawData()
其他改动
- update: 更新依赖版本
v1.6.2
Forest v1.6.2 版本发布了!此次版本更新主要修复了 JsonPath 和 SSE 相关问题,并新增了 SSE 的监听关闭接口。
新增特性
- feat: 新增 ForestSSE.close() 监听关闭接口
- feat: 新增 ForestSSE.await() 用于阻塞等待异步监听完成
修复问题
- fix: EventSource.close() 无法正常关闭 SSE 监听
- fix: 通过JsonPath获取基本类型字段错误