之前遇到过一个bug,《spring3.2 带matrix变量的URL匹配问题》(spring3.2.3已经修复该bug),今天看到问答又有人遇到一个,在此记录下,bug可真不少,测试用例看了下,写的并不是很全面。
问题:
http://www.iteye.com/problems/95247
@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) public void findPet(@MatrixVariable Map<String, String> matrixVars, @MatrixVariable(pathVar = "petId") Map<String, String> petMatrixVars) { System.out.println(matrixVars); System.out.println(petMatrixVars); }
上面代码是spring文档中的例子,浏览器中输入:http://localhost:8080/owners/44/pets/55;q=22,33;s=23时,控制台输出:
{q=[22, 33], s=[23]} {q=[22, 33], s=[23]}
但是当输入http://localhost:8080/owners/42;q=11;r=12/pets/55;q=22,33;s=23则findPet方法没有执行,难道spring文档有错误?还是少了什么配置?
目前不支持
分析:
1、先看下springmvc官网的单元测试用例
@Test public void getLookupPathWithSemicolonContent() { helper.setRemoveSemicolonContent(false); request.setContextPath("/petclinic"); request.setServletPath("/main"); request.setRequestURI("/petclinic;a=b/main;b=c/welcome.html;c=d"); assertEquals("/welcome.html;c=d", helper.getLookupPathForRequest(request)); } @Test public void getLookupPathWithSemicolonContentAndNullPathInfo() { helper.setRemoveSemicolonContent(false); request.setContextPath("/petclinic"); request.setServletPath("/welcome.html"); request.setRequestURI("/petclinic;a=b/welcome.html;c=d"); assertEquals("/welcome.html;c=d", helper.getLookupPathForRequest(request)); }
此处可以看到,如果请求的uri是/owners/42;q=11;r=12/pets/55;q=22,33;s=23,那么request.getServletPath()实际是/owners/42,而不是期待的/owners/42/pets/55;可以参考
接下来看下springmvc如何进行url匹配的,假设此处使用的是RequestMappingHandlerMapping(http://jinnianshilongnian.iteye.com/blog/1682510):
1、
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); } HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
此处委托给UrlPathHelper去查找path
2、
public String getLookupPathForRequest(HttpServletRequest request) { // Always use full path within current servlet context? if (this.alwaysUseFullPath) { return getPathWithinApplication(request); } // Else, use path within current servlet mapping if applicable String rest = getPathWithinServletMapping(request); if (!"".equals(rest)) { return rest; } else { return getPathWithinApplication(request); } }
此处因为默认不开启alwaysUseFullPath,因此会执行getPathWithinServletMapping()
3、
public String getPathWithinServletMapping(HttpServletRequest request) { String pathWithinApp = getPathWithinApplication(request); String servletPath = getServletPath(request); String path = getRemainingPath(pathWithinApp, servletPath, false); if (path != null) { // Normal case: URI contains servlet path. return path; } else { // Special case: URI is different from servlet path. // Can happen e.g. with index page: URI="/", servletPath="/index.html" // Use path info if available, as it indicates an index page within // a servlet mapping. Otherwise, use the full servlet path. String pathInfo = request.getPathInfo(); return (pathInfo != null ? pathInfo : servletPath); } }
此处调用String servletPath = getServletPath(request); 出问题了,如果我们的url是 http://localhost:8080/owners/44;a=123/pets/55;q=22,33;s=23,那么获取的将是/owners/44,而不是/owners/42/pets/55,此处有说明:
接着执行getRemainingPath则获取到剩余部分 /pets/55;q=22,33;s=23,即和之前的单元测试一样。 所以得到的path不可能匹配模式/owners/{ownerId}/pets/{petId},但是匹配/pets/{petId}(但没有意义了),所以失败了。
如
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET) public void findPet(@MatrixVariable Map<String, String> matrixVars, @MatrixVariable(pathVar = "petId") Map<String, String> petMatrixVars) { System.out.println(matrixVars); System.out.println(petMatrixVars); }
已提交给springsource。
相关推荐
使用maven搭建整合这三个框架,导入myeclipse即可测试使用
本文件为一个基本的项目配置,包括springmvc的基本配置,数据库连接池(c3p0)、事务管理、缓存、拦截器的配置。部分采用xml配置,部分采用注解。
这个是SpringMVC3.2的jar包,使用这个可以独立运行Springmvc。
【免费】Springmvc3.2所需要的全部jar包,亲测可用,包齐全,不信,试试就知道了,记得给个5星好评哦,么么哒
框架springmvc3.2+spring3.2+mybatis3.11整合附带jar包 附带jar包,直接导入myeclipse就能使用
springMVC3.2
SpringMVC3.2+JPA使用注解的方式环境搭建
springMVC3.2+Hibernate4+freemarker 代码框架采用springMVC3.2.4+hibernate4.2.8+freemarker2.3.16 功能方面只是一个简单的注册登录,前台使用freemarker渲染,使用了freemarker自定义标签。
springmvc关于@requestMapping和@requestParam的使用,详细代码,独立可用无需修改。
springmvc之@RequestMapping的简单demo
SpringMVC使用@ResponseBody.rar
jack-json包和配置,springmvc3.2及以下json格式支持。低版本spring福利,application/json不支持,可以用此包和配置。
maven3.05+springmvc3.2+spring3.2+hibernate3.6重写传智播客OA源代码。菜单部分采用ztree.界面有一部分使用bootstrap3.11。听了汤阳光大神的视频收获很大,也学习springmvc,期间有一个想法用springmvc来改写汤大神...
springMVC3.2+hibernate4.0+mysql5.1.27的包
1.28 springmvc 3.2 @MatrixVariable注解 1.29 spring3.2 带matrix变量的URL匹配问题 1.30 Shiro+Struts2+Spring3 加上@RequiresPermissions 后@Autowired失效 1.31 Spring事务不起作用 问题汇总 1.32 Spring3 Web ...
SpringMVC3.2 demo 集成ztree、JPA、简单登录。使用时修改数据连接persistence.xml中 访问首页在web.xml中修改。
基于springmvc3.2.x +tomcat8.0 ,使用ajax 发送restful请求处理数据
入门例子,可以运行,完整的包,具体代码说明可见:【http://wenku.baidu.com/view/0ab26ef4f705cc175527096b?fr=prin】,一样的。代码虽然不大,但可运行,有一定的启发性。
NULL 博文链接:https://huhongyu.iteye.com/blog/1757258