向?qū)ο笾械腖ist添加元素后,返回前端數(shù)據(jù)丟失

1. 現(xiàn)象

在開發(fā)中遇到了一個(gè)bug,我在一個(gè)對(duì)象的 list 屬性中add了一個(gè)新值,但是接口返回時(shí) list 并沒有被改變。

下面我用demo模擬了一下:

定義返回的對(duì)象clazz班級(jí),studentsJson 對(duì)應(yīng)數(shù)據(jù)庫中存儲(chǔ)的 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對(duì)象:

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() {
        // 模擬數(shù)據(jù)庫中查出的對(duì)象
        Clazz clazz = new Clazz();
        clazz.setName("一班");
        clazz.setStudentsJson("[{\"name\":\"zhangsan\"},{\"name\":\"lisi\"}]");
        logger.info("初始clazz對(duì)象: {}", clazz);

        List<Student> students = clazz.getStudents();
        logger.info("調(diào)用getStudents方法獲取的students: {}", students);

        students.add(new Student("wangwu"));
        logger.info("向students中添加一個(gè)新的學(xué)生后: {}", students);

        return clazz;
    }
}

請(qǐng)求接口后的輸出:

2021-05-20 11:32:28.865 [INFO ] [http-nio-8080-exec-1] [c.jiangxb.test.TestController ] 初始clazz對(duì)象: 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 ] 調(diào)用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中添加一個(gè)新的學(xué)生后: [Student{name='zhangsan'}, Student{name='lisi'}, Student{name='wangwu'}]

這里students中添加一個(gè)應(yīng)該是三個(gè)的,但是用postman調(diào)用返回后:

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

2. 原因

從controller返回后,spring mvc會(huì)對(duì)返回值進(jìn)行處理

ServletInvocableHandlerMethod#invokeAndHandle

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

在這一步會(huì)調(diào)用對(duì)象的get方法,所以手動(dòng)加入進(jìn)students中的對(duì)象被覆蓋掉了。

3. 建議

建議不要在 get/set 方法中寫任何的邏輯,這樣雖然可以簡化一些代碼,但是出現(xiàn)問題時(shí)不容易排查,會(huì)有很大的隱患,也不利于其他同事修改。

這點(diǎn)在阿里Java開發(fā)手冊(cè)(泰山版)中也有提到:

getter.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容