说明
本次升级的 Solon 版本是 3.7.0-M2, 3.7.0 版本还未正式发布,此次升级是一次兼容性测试。
官网对 3.7 的说明「https://solon.noear.org/article/1206」,重点是 snack3 升级到 snack4。如果有使用 snack 序列化的话需要重点关注。
升级
如果有显示的引入
snack3或者solon-serialization-snack3或者solon-config-snack3, 都需要修改成对应的 snack4 的版本。因为 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
public class SerializerDemo {
//ps: 这前需要使用 Fastjson2RenderFactory, Fastjson2ActionExecutor 两个对象,且表意不清晰 //(仍可使用)
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 未生效的。
修改继承类时注意
ObjectEncoder和ObjectPatternEncoder的区别,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
public class DemoConfig {
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;
public ONode encode(EncodeContext ctx, T value, ONode node) {
if (value == null) {
return node;
}
return encode(node, value._getAttrs());
}
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,多了返回值。可以通过下面两个方法中的一个的避免这个问题。
- 去除
@Accessors(chain = true) - 或者修改 Feature.Write_AllowUseSetter,setter 优先,没有setter 用 字段。
- 去除