背景
项目在本地运行时调用Feign接口, 返回信息正确; 但是一旦线上部署运行, 就会发现对象的信息没有正确赋值; 本地Debug的时候也一直无法重现, 接下来便排查这个问题
过程
使用阿里的jvm工具 Arthas发现返回的对象, 字段名称已经被混淆掉了. 结合jackson反序列时的特性(先使用get/set,在使用field
), 不难定位到问题所在, 返回的bean字段缺少了set方法
- Arthas排查命令:
watch com.demo.xx queryUserPage "{returnObj}" -x 2
- jackson反序列化源码
通过SettableBeanProperty
进行属性赋值,MethodProperty
缺失时使用FieldProperty
, 这就不难解释为何本地无法重现, 因为本地运行的class没有被混淆, 可以通过字段名称进行赋值; 但是打包之后字段信息已经被抹除了所以无法赋值
demo验证
编写测试的bean --> 混淆打包, 配置参考 --> IDEA右键jar包, Add as Library --> 运行demo代码 , name属性为空
User类
public class User {
private String name, city;
public User() {
}
public User(String name) {
this.name = name;
}
//name不提供set方法
}
Demo类
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
User user = new User("jaychou").setCity("taibei");
String str = mapper.writeValueAsString(user);
//反序列化,name的值没有读取出来
User parseUser = mapper.readValue(str, User.class);
assert parseUser.getName() == null;
}
解决
提供set方法, 或者不使用混淆
网友评论