1. 程式人生 > >SpringMVC對PathVariable的特殊字元.的處理預設是檔案字尾

SpringMVC對PathVariable的特殊字元.的處理預設是檔案字尾

        作為程式狗,生命不息,bug不止。在“止”這些bug的征程上,很討厭遇到奇奇怪怪的bug,也很開心遇到這些奇奇怪怪的bug。通過暴露的這些bug,愈挫愈勇的去掌握欠缺的某個技術點或思維點。

       對,一個痛苦而開心的過程。

bug現象:

A元件的介面實現邏輯上用到了訪問B元件的關於使用名字去查詢某表記錄的介面。奇怪的是,當通過再正常不過的http請求訪問時

String bUrl = "http://127.0.0.1:8184/user/%s";
String username = "[email protected]";
LinkedHashMap map = HttpRequestUtils.requestForObject(RequestMethod.GET,
           String.format(bUrl, username), null, LinkedHashMap.class);
//B元件介面接到的username不是
[email protected]
而是[email protected], //如果請求的是[email protected],會變成[email protected],也就是丟掉最後一個.及後邊的字元, //這樣引數變了,自然返回的結果就不是正確的了

B元件被訪問的介面類似這樣:

 @RequestMapping(value = "/user/{username}", method = {RequestMethod.GET})
 @ResponseBody
 public LinkedHashMap getUserById(@PathVariable("username") String username) {
     LinkedHashMap<String, String> result = new LinkedHashMap<>();
     //......餘下程式碼省略
 }

是的,真是個神奇的bug。貌似A元件很無辜,它傳遞的引數無誤呀,B元件也很無辜,從接到引數那個刻引數就不對了,怪我嗎?經過查驗,A、B元件上都不含有任何對請求url的字元內容上的攔截或過濾處理。

所以嘍,好奇怪呀。

其實B元件一點兒都不無辜,就是它的問題。

原因:

SpringMVC對PathVariable標註的路徑的引數的處理上預設.後面的是檔案字尾,

用於url,例如:http://127.0.0.1:8080/user/login.html或者http://127.0.0.1:8080/user/login.do

所以,B元件接到的引數就是[email protected]了,總是丟掉最後一個.以及後邊的字元。

解決辦法:

@RequestMapping(value = "/user/{username:.*}", method = {RequestMethod.GET})

在url宣告上使用:.*來表示獲取整個引數,不將.後的內容做檔案字尾處理。

是的,這屬於SpingMVC對特殊字元的處理

特別要指出的是: 關於特殊字元有是需要特別限制約定,例如點,需要在業務上特別指出不能使用單個點作為使用者名稱,不然對於本文的例子來說,單個點的話,不能進入B元件的接口裡(http://127.0.0.1:8080/user/.會解析成http://127.0.0.1:8080/user根本不是/user/{username}介面,存在介面訪問異常417的bug。