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]而是123@,
//如果请求的是[email protected],会变成123@..,也就是丢掉最后一个.及后边的字符,
//这样参数变了,自然返回的结果就不是正确的了

B组件被访问的接口类似这样:

 @RequestMapping(value = "/user/{username}", method = {RequestMethod.GET})
 @ResponseBody
 public LinkedHashMap getUserById(@PathVariable("username") String username) {
     LinkedHashMap 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组件接到的参数就是123@了,总是丢掉最后一个.以及后边的字符。

解决办法:

@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。

你可能感兴趣的:(Java,Spring)