SpringBoot讀取yml的一個bug

Wayne_Kdl發表於2019-12-06

本文章的產生是對一個bug的總結,是一次自底向上的記錄,並不打算有一個全域性的認識,以後有機會可以系統分析。
git地址:github.com/fw103699437…

bug展示

application.yml內容

num: 0010
複製程式碼

程式碼

    @Autowired
    Environment environment;
    @Login
    @RequestMapping("/method")
    public Entity method(@LoginUser Entity entity, @RequestBody Entity entity1){
        System.out.println(environment.getProperty("num"));
        return entity;
    }
複製程式碼

結果

8
複製程式碼

能看到環境裡的屬性與yml配置檔案裡的屬性不一致
專案裡配置檔案並不是10,這裡做了一些簡化,可以很容易猜測到,應該是讀取的時候,把0010當作八進位制了

bug trace

話不多說,直接上圖,如果不夠清晰,可以點選連結 www.processon.com/view/link/5…

大致流程就是:
1:容器啟動 2:觸發監聽 3:響應監聽讀取配置 4:利用snakeyaml來解析yml 5:解析map鍵值對 6:解析map的value(此時出了問題)

出問題的程式碼如下

public class ConstructYamlInt extends AbstractConstruct {
        @Override
        public Object construct(Node node) {
            String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
            int sign = +1;
            char first = value.charAt(0);
            if (first == '-') {
                sign = -1;
                value = value.substring(1);
            } else if (first == '+') {
                value = value.substring(1);
            }
            int base = 10;
            if ("0".equals(value)) {
                return Integer.valueOf(0);
            } else if (value.startsWith("0b")) {
                value = value.substring(2);
                base = 2;
            } else if (value.startsWith("0x")) {
                value = value.substring(2);
                base = 16;
                //因為我們是0010,因此進入這裡,base即進位制
            } else if (value.startsWith("0")) {
                value = value.substring(1);
                base = 8;
            } else if (value.indexOf(':') != -1) {
                String[] digits = value.split(":");
                int bes = 1;
                int val = 0;
                for (int i = 0, j = digits.length; i < j; i++) {
                    val += Long.parseLong(digits[j - i - 1]) * bes;
                    bes *= 60;
                }
                return createNumber(sign, String.valueOf(val), 10);
            } else {
                return createNumber(sign, value, 10);
            }
            return createNumber(sign, value, base);
        }
    }
複製程式碼

SpringBoot讀取yml的一個bug

解決

既然看到了出問題的地方,那麼就只要讓value不以0開頭就好了,拿雙引號括起來就好了。(或者不用yml?哈哈哈哈)

加雙引號之後

0010
複製程式碼

改為properties之後

0010
複製程式碼

想法

以後可以補一下spring監聽機制和載入檔案(包括系統屬性、bootstrap/application,properties/yml的區別之類的)

相關文章