1. 程式人生 > >ajax呼叫介面資料錯亂的原因

ajax呼叫介面資料錯亂的原因

        前段時間在做專案的時候遇到一個問題,在開發webapp的時候使用ajax呼叫後端介面的時候,出現了介面資料錯亂的問題,現在總結一下

問題描述:

        同一個頁面同時呼叫多個介面:A、B、C、D、E,正常返回結果應該是A-a, B-b, C-c,D-d,E-e。在網路環境比較好的時候,沒有問題,然而,在網路環境比較差的時候,錯誤出現了。返回結果中至少有兩個介面返回的結果被其他介面的資料覆蓋,結果變成了A-a, B-c, C-c,D-e,E-e,或者A-b, B-b, C-b,D-d,E-e ...... 結果被覆蓋的情況完全隨機,每次都可能不一樣,相同的是每次都會錯亂。

開始定位問題

        問題在前端,那就從前端開始,寫一個測試頁面,請求路徑為我們的測試服:


檢視控制檯,結果:錯亂,和之前的錯誤預估一樣,網路環境差的時候,資料錯亂

沒有對比就沒有發言權,所以這次把請求路徑變為自己的開發環境:


檢視控制檯,結果竟然還是錯亂,這個問題首次在本地重現了,ok,至少進了一步。

再看看是不是偶然事件,於是多重新整理幾遍,結果無一例外的全部是資料錯亂

之前直接甩鍋到前端,因為前端用的框架和我之前用的框架不一樣,為了確定是不是框架的原因,我特意直接用jQuery寫ajax呼叫介面,看來框架的原因可以排除了

排除了前端的問題,那就是後端介面的問題了,然後我開始查介面的實現方法,突然發現一個可能的問題,後端使用SpringMVC,所有介面都繼承自同一個Controller


    
  1. ......
  2. ......
  3. /**
  4. * 通用工具類
  5. * @author heh
  6. */
  7. @SuppressWarnings({ "unchecked", "rawtypes" })
  8. public class BaseController {
  9. ......
  10. ......
  11. /**
  12. * 提示(用於返回操作結果)
  13. */
  14. protected Tip tip = new Tip();
  15. ......
  16. ......
  17. }

然後所有的介面都統一使用這個tip作為資料容器然後返回資料,是這樣寫的


    
  1. ......
  2. @Controller
  3. @SuppressWarnings({ "rawtypes", "unchecked", "unused" })
  4. public class WSControllerImpl extends BaseController implements ...... {
  5. ......
  6. @Override
  7. public Tip getUserMessage(HttpServletRequest req) {
  8. String messageid = req.getParameter( "id");
  9. tip.success(userService.getMessageById(messageid));
  10. return tip;
  11. }
  12. ......
  13. }

之前為了減少重複程式碼,就把這個tip容器放到了BaseController裡,供其子類呼叫,沒有考慮到不同介面呼叫這個公共引數的時候,不是獨佔呼叫,而是所有的介面都可以修改,所以多個介面同時呼叫的時候,就會出現A介面呼叫完畢,還沒有返回的時候,tip已經被B介面修改了,所以造成A介面返回的資料和B介面返回的資料變成一樣的情況。至此確定了問題。

問題確定之後,解決就簡單了,只要讓每個介面的tip單獨new出來即可,不使用公共資源

回顧確定問題的過程,發現多介面併發執行的時候,少於4個介面的時候不會錯亂,大於或等於4個介面的時候,問題必然出現。這也算是一個低階錯誤了。


總結:在多個子類訪問同一個父類的資源的時候,資料類資源最好是不可更改的型別,不要讓多個子類同時修改父類的內容。父類的公用內容儘量使用工具操作類的程式碼,不要用資料共享的內容。程式碼還是要踏踏實實寫,偷懶很容易出問題。


        前段時間在做專案的時候遇到一個問題,在開發webapp的時候使用ajax呼叫後端介面的時候,出現了介面資料錯亂的問題,現在總結一下

問題描述:

        同一個頁面同時呼叫多個介面:A、B、C、D、E,正常返回結果應該是A-a, B-b, C-c,D-d,E-e。在網路環境比較好的時候,沒有問題,然而,在網路環境比較差的時候,錯誤出現了。返回結果中至少有兩個介面返回的結果被其他介面的資料覆蓋,結果變成了A-a, B-c, C-c,D-e,E-e,或者A-b, B-b, C-b,D-d,E-e ...... 結果被覆蓋的情況完全隨機,每次都可能不一樣,相同的是每次都會錯亂。

開始定位問題

        問題在前端,那就從前端開始,寫一個測試頁面,請求路徑為我們的測試服:


檢視控制檯,結果:錯亂,和之前的錯誤預估一樣,網路環境差的時候,資料錯亂

沒有對比就沒有發言權,所以這次把請求路徑變為自己的開發環境:


檢視控制檯,結果竟然還是錯亂,這個問題首次在本地重現了,ok,至少進了一步。

再看看是不是偶然事件,於是多重新整理幾遍,結果無一例外的全部是資料錯亂

之前直接甩鍋到前端,因為前端用的框架和我之前用的框架不一樣,為了確定是不是框架的原因,我特意直接用jQuery寫ajax呼叫介面,看來框架的原因可以排除了

排除了前端的問題,那就是後端介面的問題了,然後我開始查介面的實現方法,突然發現一個可能的問題,後端使用SpringMVC,所有介面都繼承自同一個Controller


  
  1. ......
  2. ......
  3. /**
  4. * 通用工具類
  5. * @author heh
  6. */
  7. @SuppressWarnings({ "unchecked", "rawtypes" })
  8. public class BaseController {
  9. ......
  10. ......
  11. /**
  12. * 提示(用於返回操作結果)
  13. */
  14. protected Tip tip = new Tip();
  15. ......
  16. ......
  17. }

然後所有的介面都統一使用這個tip作為資料容器然後返回資料,是這樣寫的


  
  1. ......
  2. @Controller
  3. @SuppressWarnings({ "rawtypes", "unchecked", "unused" })
  4. public class WSControllerImpl extends BaseController implements ...... {
  5. ......
  6. @Override
  7. public Tip getUserMessage(HttpServletRequest req) {
  8. String messageid = req.getParameter( "id");
  9. tip.success(userService.getMessageById(messageid));
  10. return tip;
  11. }
  12. ......
  13. }

之前為了減少重複程式碼,就把這個tip容器放到了BaseController裡,供其子類呼叫,沒有考慮到不同介面呼叫這個公共引數的時候,不是獨佔呼叫,而是所有的介面都可以修改,所以多個介面同時呼叫的時候,就會出現A介面呼叫完畢,還沒有返回的時候,tip已經被B介面修改了,所以造成A介面返回的資料和B介面返回的資料變成一樣的情況。至此確定了問題。

問題確定之後,解決就簡單了,只要讓每個介面的tip單獨new出來即可,不使用公共資源

回顧確定問題的過程,發現多介面併發執行的時候,少於4個介面的時候不會錯亂,大於或等於4個介面的時候,問題必然出現。這也算是一個低階錯誤了。


總結:在多個子類訪問同一個父類的資源的時候,資料類資源最好是不可更改的型別,不要讓多個子類同時修改父類的內容。父類的公用內容儘量使用工具操作類的程式碼,不要用資料共享的內容。程式碼還是要踏踏實實寫,偷懶很容易出問題。