美文网首页
向对象中的List添加元素后,返回前端数据丢失

向对象中的List添加元素后,返回前端数据丢失

作者: silence_J | 来源:发表于2021-05-21 11:16 被阅读0次

    1. 现象

    在开发中遇到了一个bug,我在一个对象的 list 属性中add了一个新值,但是接口返回时 list 并没有被改变。

    下面我用demo模拟了一下:

    定义返回的对象clazz班级,studentsJson 对应数据库中存储的 Json Array 字符串,students是将字符串处理后返回的列表:

    public class Clazz {
    
        private String name;
    
        private String studentsJson;
    
        private List<Student> students;
    
        public List<Student> getStudents() {
            if (!StringUtils.isEmpty(studentsJson)) {
                students = JSON.parseArray(studentsJson, Student.class);
                return students;
            }
            return students;
        }
    
        public void setStudents(List<Student> students) {
            this.students = students;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getStudentsJson() {
            return studentsJson;
        }
    
        public void setStudentsJson(String studentsJson) {
            this.studentsJson = studentsJson;
        }
    
        @Override
        public String toString() {
            return "Clazz{" +
                    "name='" + name + '\'' +
                    ", studentsJson='" + studentsJson + '\'' +
                    ", students=" + students +
                    '}';
        }
    }
    

    Student对象:

    public class Student {
    
        private String name;
    
        // 省略 get/set 方法 ...
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    接口模拟:

    @RestController
    public class TestController {
    
        Logger logger = LoggerFactory.getLogger(TestController.class);
    
        @GetMapping("/test")
        public Clazz showClazz() {
            // 模拟数据库中查出的对象
            Clazz clazz = new Clazz();
            clazz.setName("一班");
            clazz.setStudentsJson("[{\"name\":\"zhangsan\"},{\"name\":\"lisi\"}]");
            logger.info("初始clazz对象: {}", clazz);
    
            List<Student> students = clazz.getStudents();
            logger.info("调用getStudents方法获取的students: {}", students);
    
            students.add(new Student("wangwu"));
            logger.info("向students中添加一个新的学生后: {}", students);
    
            return clazz;
        }
    }
    

    请求接口后的输出:

    2021-05-20 11:32:28.865 [INFO ] [http-nio-8080-exec-1] [c.jiangxb.test.TestController ] 初始clazz对象: Clazz{name='一班', studentsJson='[{"name":"zhangsan"},{"name":"lisi"}]', students=null}
    2021-05-20 11:32:28.916 [INFO ] [http-nio-8080-exec-1] [c.jiangxb.test.TestController ] 调用getStudents方法获取的students: [Student{name='zhangsan'}, Student{name='lisi'}]
    2021-05-20 11:32:28.917 [INFO ] [http-nio-8080-exec-1] [c.jiangxb.test.TestController ] 向students中添加一个新的学生后: [Student{name='zhangsan'}, Student{name='lisi'}, Student{name='wangwu'}]
    

    这里students中添加一个应该是三个的,但是用postman调用返回后:

    {
        "name": "一班",
        "studentsJson": "[{\"name\":\"zhangsan\"},{\"name\":\"lisi\"}]",
        "students": [
            {"name": "zhangsan"},
            {"name": "lisi"}
        ]
    }
    

    2. 原因

    从controller返回后,spring mvc会对返回值进行处理

    ServletInvocableHandlerMethod#invokeAndHandle

    this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
    

    在这一步会调用对象的get方法,所以手动加入进students中的对象被覆盖掉了。

    3. 建议

    建议不要在 get/set 方法中写任何的逻辑,这样虽然可以简化一些代码,但是出现问题时不容易排查,会有很大的隐患,也不利于其他同事修改。

    这点在阿里Java开发手册(泰山版)中也有提到:

    getter.png

    相关文章

      网友评论

          本文标题:向对象中的List添加元素后,返回前端数据丢失

          本文链接:https://www.haomeiwen.com/subject/tucwjltx.html