Closed venusdrogon closed 6 years ago
今天我们的某个大型商城做UAT, 客户在后台创建了个 商品code 是 0900-PK.3.58-4-A004 的商品, 然后界面可以搜索到, 但是点击进入明细页面报错了
0900-PK.3.58-4-A004
分析logback 日志, 发现了异常, 以及一个怪怪的 商品code
0900-PK.3.58-4-A004 到了controller 层,变成了 0900-PK.3
0900-PK.3
检查 Controller 中的 rrequestMapping , 感觉没毛病
事务反常必有妖, 老司机遇到了新问题, 我们做过了那么多的官方商城, 商品code 通常都是规整的, 比如 ABC1234, 第一次遇到 0900-PK.3.58-4-A004 的商品Code
OK, let go, 捉妖去~~
源码面前,了无秘密, 开启debug 大法
对于@PathVariable 的参数, 值其实是解析之后,转成map 存放在 request 作用域中, name是 常量 org.springframework.web.servlet.HandlerMapping#URI_TEMPLATE_VARIABLES_ATTRIBUTE
当我去看这个属性值的时候, 发现 uriTemplateVars map 中值 已经被解析成
storeId=2, itemCode=0900-PK.3
那顺藤摸瓜,往上走
发现原来的 路径格式是 /item/{storeId}/{itemCode} ,变成了 /item/{storeId}/{itemCode}.*
/item/{storeId}/{itemCode}
/item/{storeId}/{itemCode}.*
好神奇
再往上走 到了 org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPattern(String, String)
org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPattern(String, String)
private String getMatchingPattern(String pattern, String lookupPath) { if (pattern.equals(lookupPath)) { return pattern; } if (this.useSuffixPatternMatch) { if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) { for (String extension : this.fileExtensions) { if (this.pathMatcher.match(pattern + extension, lookupPath)) { return pattern + extension; } } } else { boolean hasSuffix = pattern.indexOf('.') != -1; if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) { return pattern + ".*"; } } } if (this.pathMatcher.match(pattern, lookupPath)) { return pattern; } if (this.useTrailingSlashMatch) { if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) { return pattern +"/"; } } return null; }
表示, 如果 开启了 useSuffixPatternMatch (默认值是 true) ,且路径中有 .号, 将会把. 后面的部分解析为 扩展名
因此就变成了 最后面一个 . 之前的是 商品code ,这就导致了 0900-PK.3.58-4-A004 到了controller 层,变成了 0900-PK.3
如何解决呢?
直接在 mvc:annotation-driven 加入 <mvc:path-matching suffix-pattern="false" />
<mvc:path-matching suffix-pattern="false" />
<mvc:annotation-driven> <!-- add by feilong ,do with http://127.0.0.1:8091/item/2/0900-PK.3.58-4-A004 see http://jira.baozun.cn/browse/BBFED-3045 --> <mvc:path-matching suffix-pattern="false" /> ...
如果该特性, since spring 3.1
可以在 pdp controller 中把路径改成 /item/{storeId}/{itemCode:.+}
/item/{storeId}/{itemCode:.+}
新建个单独的类 MvcConfig
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @Configuration public class MvcConfig extends WebMvcConfigurationSupport{ @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping(); handlerMapping.setUseSuffixPatternMatch(false); handlerMapping.setUseTrailingSlashMatch(false); return handlerMapping; } }
https://stackoverflow.com/questions/16332092/spring-mvc-pathvariable-with-dot-is-getting-truncated
https://blog.csdn.net/ruipheng/article/details/65438703
see https://github.com/venusdrogon/feilong-spring/wiki/%E5%BD%93%E5%95%86%E5%93%81%E7%BC%96%E7%A0%81%E9%81%87%E5%88%B0%E4%BA%86.%E5%8F%B7,-spring-restful-@PathVariable-%E5%BA%94%E5%AF%B9%E6%8E%AA%E6%96%BD
1. 背景
今天我们的某个大型商城做UAT, 客户在后台创建了个 商品code 是
0900-PK.3.58-4-A004
的商品, 然后界面可以搜索到, 但是点击进入明细页面报错了分析logback 日志, 发现了异常, 以及一个怪怪的 商品code
0900-PK.3.58-4-A004
到了controller 层,变成了0900-PK.3
检查 Controller 中的 rrequestMapping , 感觉没毛病
2. 排查
事务反常必有妖, 老司机遇到了新问题, 我们做过了那么多的官方商城, 商品code 通常都是规整的, 比如 ABC1234, 第一次遇到
0900-PK.3.58-4-A004
的商品CodeOK, let go, 捉妖去~~
源码面前,了无秘密, 开启debug 大法
对于@PathVariable 的参数, 值其实是解析之后,转成map 存放在 request 作用域中, name是 常量 org.springframework.web.servlet.HandlerMapping#URI_TEMPLATE_VARIABLES_ATTRIBUTE
当我去看这个属性值的时候, 发现 uriTemplateVars map 中值 已经被解析成
storeId=2, itemCode=0900-PK.3
那顺藤摸瓜,往上走
发现原来的 路径格式是
/item/{storeId}/{itemCode}
,变成了/item/{storeId}/{itemCode}.*
好神奇
再往上走 到了
org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPattern(String, String)
表示, 如果 开启了 useSuffixPatternMatch (默认值是 true) ,且路径中有 .号, 将会把. 后面的部分解析为 扩展名
因此就变成了 最后面一个 . 之前的是 商品code ,这就导致了
0900-PK.3.58-4-A004
到了controller 层,变成了0900-PK.3
如何解决呢?
3. 解决方案
方案A: 全局统一处理
直接在 mvc:annotation-driven 加入
<mvc:path-matching suffix-pattern="false" />
如果该特性, since spring 3.1
方案B
可以在 pdp controller 中把路径改成
/item/{storeId}/{itemCode:.+}
方案C
新建个单独的类 MvcConfig
4. 参考
https://stackoverflow.com/questions/16332092/spring-mvc-pathvariable-with-dot-is-getting-truncated
https://blog.csdn.net/ruipheng/article/details/65438703