Ohhnews

分类导航

$ cd ..
foojay原文

BoxLang 1.16.0发布:增强HTTP客户端控制与CFML兼容性

#boxlang#1.16.0#http客户端#cfml兼容性#java集成

[LOADING...]

BoxLang 1.16.0 发布了,共解决了 50 个问题,涵盖新功能、改进和缺陷修复。本次发布的核心主题是“控制”:控制 HTTP 客户端的创建与复用方式,控制请求失败时的行为,控制响应允许缓冲的数据量,控制 Java 类路径重新加载的时机,并在进行迁移时更紧密地对齐 CFML 的边界行为。

HTTP 客户端生命周期与可观测性

HTTP 技术栈是本次发布中投入最大的部分。

HTTP 与 SOAP 客户端现在通过 Box 缓存进行缓存BL-2559)。客户端不再在每次调用时无控制地创建,而是被池化并复用,这意味着可预测的超时行为,以及负载下显著降低的创建开销。这一点在高流量集成代码中尤为重要,因为客户端构建一直在悄然占据大部分请求成本。

新增 onHTTPError 事件BL-2558)提供了客户端级错误拦截。无需在每个出站调用中包裹防御性的 try/catch 代码块,错误处理可以在应用程序级别集中进行:记录日志、发出指标、触发熔断器,或转换响应。

class {

    function onHTTPError( event, data ){
        var httpResult = data.result
        var target     = data.target

        application.logger.error(
            "HTTP call failed to #target.url#",
            {
                statusCode : httpResult.statusCode ?: "none",
                errorDetail : httpResult.errorDetail ?: "",
                timeout : httpResult.timeout ?: false
            }
        )
    }

}

HTTP 客户端配置和请求目标元数据现已暴露在 BoxLang 统计信息中BL-2562),BoxHTTPClient 会跟踪已观测的主机BL-2566)。这两项功能共同回答了一个过去只能靠猜测的问题:这个应用程序实际上在与什么通信,又是如何配置来通信的?这些数据可以直接用于运维仪表盘和流量分析。

最大流内容长度控制BL-2565)可防止无限制的响应缓冲。一个行为异常的上游服务向内存中流入数 GB 数据,现在只会造成有界失败,而不会导致内存溢出事件。

作为 HTTP 工作的收尾,底层连接失败不再导致结果中缺少 fileContentBL-2556),并且修正了安全协议协商期间 Basic Auth 字符集分配的问题(BL-2567)。

反向代理后的 MiniServer 部署

通过新的配置设置,在 nginx、Traefik、ALB 或任何其他代理层之后运行 BoxLang MiniServer 变得更加顺畅。

useProxyHeadersBL-2598)指示运行时信任并遵循转发的请求头,从而使客户端 IP、协议和主机反映原始请求,而非代理跳转。

{

    "useProxyHeaders": true
    
}

除此之外,MiniServer 不再因尾斜杠处理而重写 /ws 请求BL-2572),这解除了 WebSocket 端点的阻塞;MiniServer 现在默认将表单字段字符集编码为 UTF-8BL-2613),因此带重音字符和非拉丁文字可以在无需额外配置的情况下通过表单提交保留下来。

Struct 流

Struct 与数组和查询一样,获得了一流的 Java Stream 支持(BL-2590)。新增三个成员:stream()keyStream()valueStream()

inventory = {
    widgets  : 42,
    gadgets  : 7,
    sprockets: 0,
    gizmos   : 118
}

// Keys with zero stock
outOfStock = inventory.stream()
    .filter( entry -> entry.getValue() == 0 )
    .map( entry -> entry.getKey() )
    .toList()

// Total units on hand
totalUnits = inventory.valueStream()
    .mapToInt( qty -> qty )
    .sum()

// Sorted key listing
sortedKeys = inventory.keyStream()
    .sorted()
    .toList()

由于这些是真正的 Java 流,因此完整的 java.util.stream 接口都可用:并行处理、收集器、扁平映射,以及 JDK 提供的所有终止操作。中间没有自定义的 BoxLang 抽象层。

Java 库热重载

javasettings.reloadOnChange 现已实现(BL-2588)。将应用程序指向一组 JAR 文件后,运行时无需重启即可获取更改,这大大缩短了在开发 BoxLang 代码的同时并行开发 Java 库时的循环周期。

bx:application
    name = "reloadOnChangeApp"
    javaSettings = {
        loadPaths     : [ "/path/to/libs/helloworld.jar" ],
        reloadOnChange: true
    }

与此相辅相成的是,dynamicClassLoader.addPaths() 现在接受单个 JAR 或类文件路径BL-2585),而不再要求必须是目录。

getRequestClassLoader().addPaths( "/opt/app/lib/acme-utils.jar" )

这里还包含两个相关修复:当类加载器被包装在 DynamicObject 中时,createObject() 不再报错(BL-2587);相对类解析现在包含基础模板路径查找(BL-2582)。

压缩包格式扩展支持

compress()extract() 增加了面向 Unix 的流水线实际会使用的压缩包格式(BL-2592)。

compress() 现在支持 bzipbzip2tartar.bztbztbz2tgztar.gzextract() 支持 bzipbzip2tartbztbz2tgztar.gz

compress(
    source      = "/tmp/project",
    destination = "/tmp/project.tar.gz",
    format      = "tar.gz"
)

extract(
    source      = "/tmp/project.tbz2",
    destination = "/tmp/project-out",
    format      = "tbz2"
)

请注意,extract() 的参数名现在是 destination 而不是 target,转译器会自动映射旧形式(BL-2591)。同时修复了将目录压缩到其自身内部文件中的问题(BL-2573)。我们还提供了一份新的压缩指南:https://boxlang.ortusbooks.com/boxlang-framework/file-handling/compression

查询增强

query.findColumn() 增加了兼容性行为(BL-2609),返回命名列的位置索引。

users = queryNew(
    "id,name,email",
    "integer,varchar,varchar",
    [
        [ 1, "Ana", "ana@example.com" ],
        [ 2, "Luis", "luis@example.com" ]
    ]
)

nameColumnIndex  = users.findColumn( "name" )
emailColumnIndex = users.findColumn( "email" )

查询层还进行了一轮扎实的正确性修复:query.filter 现在能够处理 null 列值(BL-2563);QoQ 不再在空列表参数上报错(BL-2575);在非字符串查询列上设置默认值时的类型转换错误已解决(BL-2606);复合运算符在查询列上可以正确工作(BL-2611);在兼容模式下,Oracle null refcursor 输出参数不再默认设为空字符串(BL-2603)。现在也允许混合使用位置和索引形式的 procresultBL-2601)。

CFML 与转译器一致性

1.16.0 继续稳步推进,缩小 CFML 代码库与转译输出之间的行为差距:

  • listAppend() 现在同时以成员方法形式和内置函数(BIF)形式进行转译(BL-2580
  • CFC 和 BX 文件可以在兼容场景中使用(BL-2610
  • e.extendedInfo 现在可以在 CF 场景中设置(BL-2586
  • 类中的默认 output 注解行为已放宽(BL-2589
  • 补全了 cfloop 结构体属性的缺失实现路径(BL-2554
  • DateTime 转换器现在支持 M/d/yyyy hh:mm: ss.SSSBL-2583
  • Cookie 的 expires="never" 不再导致类型转换失败(BL-2602

闭包、接口与 Java 互操作

三项修复改进了 BoxLang 函数在传递给 Java 时的行为:

  • 代理到函数式接口的闭包现在会遵循默认方法(BL-2381
  • 使用通用代理覆盖接口默认方法现在可以正确工作(BL-2608
  • 修复了闭包在调用用户自定义函数(UDF)时绑定到非词法变量的问题(BL-2552

稳定性与性能

其余修复涉及空白管理、文件循环、解析和类型转换。

空白管理不再破坏 JavaScript 输出(BL-2578),并能正确移除前导空格(BL-2581)。文件循环修复了 indexitem 处理(BL-2596)、字符支持(BL-2597),以及要求必须提供 itemindex 其中一项的验证(BL-2604)。

在解析器方面,嵌套 switch 中的 rethrow 现在可以正确解析(BL-2584),assert 语句中的 null 不再导致解析器出错(BL-2605)。类型转换修复包括 urlDecode( 0 )BL-2553)、structKeySet() 强制将键转换为字符串(BL-2570)、formatBaseN()Long 输入的支持(BL-2571),以及列表追加/前置时 includeEmptyFields 的行为(BL-2579)。按位内置函数已扩展支持 long 值(BL-2561)。

有两项性能和稳定性改进值得特别提及:比较运算符中的性能回退已被修正(BL-2560),并且消除了 getClassMetadata 中的 NullPointerExceptionBL-2564)。

输出管道中还有一个新增功能:在写入浏览器的拦截中现在可以设置 dispositionBL-2577)。

升级

对于重度依赖 HTTP 集成、在代理后运行 MiniServer,或依赖 CFML 兼容性边界行为的团队,BoxLang 1.16.0 是推荐的更新版本。

每个受支持运行时的安装和升级说明,请参阅 BoxLang 安装指南

资源

该文章《BoxLang 1.16.0 发布!》最初发布在 foojay 上。