本文章的產生是對一個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);
}
}
複製程式碼
解決
既然看到了出問題的地方,那麼就只要讓value不以0開頭就好了,拿雙引號括起來就好了。(或者不用yml?哈哈哈哈)
加雙引號之後
0010
複製程式碼
改為properties之後
0010
複製程式碼
想法
以後可以補一下spring監聽機制和載入檔案(包括系統屬性、bootstrap/application,properties/yml的區別之類的)