### 兼容说明

这个版本主要是在内核启用了 `slf4j-api` 和 `solon-expression`。并启用了新接口 `EntityConverter`（v3.6.0 支持）, `MethodArgumentResolver`（v3.6.1 支持）。主要是内部变化，外部体验保持兼容。另外，文件上传方面有多处优化。

兼容问题：

* `SolonProps:argx` 改为 MultiMap 类型。如果有用到 `Solon.cfg().argx()`，重新编译即可。

提醒：

* 有用到 `Condition:onProperty` 的应用，建议改为 `Condition:onExpression` （作好测试）


部分弃用对照表：



| 弃用 | 新用 | 备注 |
| -------- | -------- | -------- |
| `app.converterManager()`     | `app.converters()`     | 简化     |
| `app.serializerManager()`     | `app.serializers()`     | 简化     |
| `app.renderManager()`     | `app.renders()`     | 简化     |
| `app.factoryManager()`     | `app.factories()`     | 简化     |
| `app.chainManager()`     | `app.chains()`     | 简化     |



### 具体更新



* 新增 `solon-server-grizzly` 插件
* 新增 `solon-server-grizzly-add-websocket` 插件
* 新增 `solon-server-tomcat` 插件（基于 tomcat v9.0 适配）
* 新增 `solon-server-tomcat-jakarta` 插件（基于 tomcat v11.0 适配）
* 新增 `solon-server-undertow-jakarta` 插件（基于 undertow v2.3 适配）
* 完善 `solon-server-jetty-jakarta` 插件（基于 jetty v12 适配）
* 完善 `solon-server-jetty-add-jsp-jakarta` 插件（基于 jetty v12 适配）
* 完善 `solon-server-jetty-add-websocket-jakarta` 插件（基于 jetty v12 适配）
* 调整 `solon-serialization-*` 弱化 ActionExecuteHandler, Render 的定制，改为 XxxxSerializer 对外定制
* 调整 `solon` LogIncubator 接口迁移到内核，由内核控制加载时机（权重提高）
* 调整 `solon` EntityConverter 接口（替代 Render 和 ActionExecuteHandler 接口），旧接口仍可用
* 调整 `solon` SolonProps:argx 改为 MultiMap 类型（支持多值），NvMap 标为弃用
* 引入 `slf4j-api` 替代 `solon` 内的 LogUtil（减少中转代码）
* 引入 `solon-expression` 替代 `solon` 内的模板表达式工具（仍可使用）
* 添加 `solon` Condition:onExpression（采用 SnEL 表达式）用于替代 onProperty（标为弃用）
* 添加 `solon` SnelUtil（基于 SnEL 且兼容旧的 TmplUtil） 替代 TmplUtil（标为弃用）//如果有 # 则为新表达式
* 添加 `solon-mvc` `List<UploadedFile>` 注入支持（用 `UploadedFile[]` 性能更好）
* 添加 `solon-server` 所有 http-server 适配 `server.request.fileSizeThreshold` 配置支持（重要升级）
* 添加 `solon` converters,serializers,renders,factories,chains（简化名自：converterManager,serializerManager,renderManager,factoryManager,chainManager）
* snakeyaml 升为 2.5
* lombok 升为 1.18.42
* jansi 升为 2.4.2
* guava 升为 33.4.8-jre
* log4j 升为 2.25.1
* fury 升为 0.10.3
* smart-http 升为 2.5.13
* reactor-core 升为 3.7.4
* graalvm.buildtools 升为 0.11.0

示例：

```java
@Managed
public class SerializerDemo {
    //ps: 这前需要使用 Fastjson2RenderFactory， Fastjson2ActionExecutor 两个对象，且表意不清晰 //（仍可使用）
    @Managed
    public void config(Fastjson2StringSerializer serializer) {
        //序列化（输出用）
        serializer.addEncoder(Date.class, s -> s.getTime());
        
        serializer.addEncoder(Date.class, (out, obj, o1, type, i) -> {
            out.writeInt64(((Date) obj).getTime());
        });

        serializer.getSerializeConfig().addFeatures(JSONWriter.Feature.WriteMapNullValue); //添加特性
        serializer.getSerializeConfig().removeFeatures(JSONWriter.Feature.BrowserCompatible); //移除特性
        serializer.getSerializeConfig().setFeatures(JSONWriter.Feature.BrowserCompatible); //重设特性

        //反序列化（收接用）
        serializer.getDeserializeConfig().addFeatures(JSONReader.Feature.Base64StringAsByteArray);
    }
}

@Managed
public class ConditionDemo(){
    //ps: 之前是用 onProperty（功能有限，不够体系化） //（仍可使用）
    @Condition(onExpression = "${demo.level:1} == '1'") //SnEL 求值表达式
    @Managed
    public void ifDemoLevel1ThenRun(){
        System.out.println("hi!");
    }
}

@Managed
public class SnelDemo {
    //ps: 之前基于 TmplUtil 实现（功能有限，不够体系化） //（仍可使用） //旧模板符号：`${}`
    @Cache(key = "oath_#{code}", seconds = 10) //SnEL 模板表达式（通过 SnelUtil 实现兼容）//新模板符号：`#{}`
    public Oauth queryInfoByCode(String code) {
        return new Oauth(code, LocalDateTime.now());
    }
    
    @CachePut(keys = "oath_#{result.code}") //(result 为返回结果)
    public Oauth updateInfo(Oauth oauth) {
        return oauth;
    }

    @CacheRemove(keys = "oath_#{oauth.code}")
    public void removeInfo(Oauth oauth) {

    }
}
```
