CrazyAirhead

疯狂的傻瓜,傻瓜也疯狂——傻方能执著,疯狂才专注!

0%

升级 Solon 3.7.0 踩坑记录

说明

本次升级的 Solon 版本是 3.7.0-M2, 3.7.0 版本还未正式发布,此次升级是一次兼容性测试。

官网对 3.7 的说明「https://solon.noear.org/article/1206」,重点是 snack3 升级到 snack4。如果有使用 snack 序列化的话需要重点关注。

升级

  1. 如果有显示的引入 snack3 或者 solon-serialization-snack3 或者 solon-config-snack3, 都需要修改成对应的 snack4 的版本。

  2. 因为 snack4 修改了包名,部分类的位置和接口,因此也需要同步修改。整体的兼容性情况,参看「https://solon.noear.org/article/1184」。

    如果编译通过基本上就是升级成功了。

可能碰到的问题

  • 接口 @Body 的请求参数或者返回值没有符合预期。

检查 snack3 是否替换干净

  • 如果有对 snack 的序列化做定制,需要先关注 3.6.0 的兼容性说明「https://solon.noear.org/article/1199」统一了序列化和反序列化。

    如果有定制,就需要修改。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @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);
    }
    }
  • 如果定制了 Encoder,Encoder 未生效的。

    修改继承类时注意 ObjectEncoderObjectPatternEncoder 的区别, ObjectEncoder 适用于修改单个类,而ObjectPatternEncoder适用于一批类,也就是基类的情况。

    以下是使用 ObjectPatternEncoder 代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    @Configuration
    public class DemoConfig {
    @Bean
    public void config(Snack4StringSerializer serializer) {
    serializer.addEncoder(Model.class, new ModelEncoder<>());

    serializer.getDeserializeConfig().addFeatures(Feature.Write_OnlyUseSetter);
    }
    }

    /**
    * @author airhead
    */
    public class ModelEncoder<T extends Model<?>> implements ObjectPatternEncoder<T> {

    /** 对 Model 和 Record 的字段名进行转换的函数。例如转成驼峰形式对 oracle 支持更友好 */
    protected static Function<String, String> fieldNameConverter = StrUtil::toCamelCase;

    @Override
    public ONode encode(EncodeContext ctx, T value, ONode node) {
    if (value == null) {
    return node;
    }

    return encode(node, value._getAttrs());
    }

    @Override
    public boolean canEncode(Object value) {
    return value instanceof Model;
    }

    protected ONode encode(ONode node, Map<String, Object> map) {
    if (CollUtil.isEmpty(map)) {
    return node;
    }

    Map<String, Object> newMap = new HashMap<>(map.size());
    for (Map.Entry<String, Object> entry : map.entrySet()) {
    String fieldName = entry.getKey();
    Object value = entry.getValue();
    String attrName = fieldName;
    if (fieldNameConverter != null) {
    attrName = fieldNameConverter.apply(fieldName);
    }
    newMap.put(attrName, value);
    }

    node.fill(newMap);

    return node;
    }
    }


  • 如果使用了 Lombok,如果指定了 @Accessors(chain = true),如果指定了`serializer.getDeserializeConfig().addFeatures(Feature.Write_OnlyUseSetter),获取的请求参数可能为空。

    因为 chain 生成的 setter 不是标准的 Bean setter,多了返回值。可以通过下面两个方法中的一个的避免这个问题。

    1. 去除 @Accessors(chain = true)
    2. 或者修改 Feature.Write_AllowUseSetter,setter 优先,没有setter 用 字段。

欢迎关注我的其它发布渠道