隔叶黄莺 The Blog of Unmi

〖隔叶黄莺三四声,挂壁飞瀑千万尘。若是人间无净土,此处为何妙语真! 隔叶黄莺四字,本非取自此句,而有寄寓他意,因见妙语,亦与予心合!〗

BlogJava 首页 新随笔 联系 聚合 管理
  380 Posts :: 106 Stories :: 1181 Comments :: 0 Trackbacks
Spring MVC 中 Controller 的层次实在是多,有些眼花缭乱了。在单个的基础上,再新加两三个叫做丰富,再多就未必是好事,反而会令人缩手新闻片脚,无从定夺。多数 Controller 都是只完成一个任务,不过也有一个像 Struts 的 DispatchAction 的那样的 Conntroller,org.springframework.web.servlet.mvc.multiaction.MultiActionController,意即在一个 Controller 中处理多个动作,如同一个业务的增、删、改可以放在一起了。不至于增、删、改各自为政,造成代码混乱、重复难以维护。

本文中的 web.xml 的 org.springframework.web.servlet.DispatcherServlet 所处理的 url-pattern 是 *.html,如何搭建 Spring MVC 项目不细加说明,可参考我前面同系列的文章。

例如,下面的 UserController,有两个签名一样的 updateUser() 和 deleteUser() 方法



用过 Struts 的 DispatchAction 的都知道,是通过 http://.../userAction.do?method=updateUser 的方式来指定执行哪个方法。那 Spring MVC中是如何定位到所需方法上呢?

Spring MVC 除了有一个叫做 HandlerMapping(把 URL 解析到 Controller) 的东西,还要把操作进一步解析到方法名上,即要找到的 Controller 上的哪个方法并执行之。缺省的方法名解析器是 InternalPathMethodNameResolver,它根据 URL 样式解析方法名。

在缺省的 BeanNameUrlHandlerMapping 和缺省的 InternalPathMethodNameResolver 协调之下,Bean 上下文可以这样配置:



这样分别通过下面的 URL 就能执行到正确的方法上去了:

http://.../updateUser.html  --  将被 UserController.updateUser() 处理
http://.../deleteUser.html   --   将被 UserController.deleteUser() 处理

但是,你应该注意到了,上面的 com.unmi.UserController 配置了两次,一来碍眼、二来原来只要 Singleton 的 UserController 实例不再是那么回事了。所以要引入 SimpleUrlHandlerMapping 对 Bean 配置进一步紧凑一下:



说是紧凑,倒不如说 Bean 配置复杂了,反正不用配置两个相同的 UserController 实例了。还是通过上面那两个 URL 来访问执行到相应的方法。

除了缺省的方法名解析器 InternalPathMethodNameResolver(注意了,Spring 中缺省的 XXX 很多用 InternalXXX 的命名),还有两种其他类型的方法名解析器:

·ParameterMethodNameResolver -- 根据请求中的参数解析执行方法名,相当于 Struts 的 DispathAction
·PropertiesMethodNameResolver -- 根据查询一个 key/value 列表解析执行方法名,相当于 Struts 的 MappingDispatchAction(用得很少)

下面逐一介绍使用上面两种方法名解析器时的 Bean 配置及相应访问的 URL。

使用 ParameterMethodNameResolver 时的 Bean 配置(为简单起见,又用回了缺省的 HandlerMapping):



这时候分别用下面的 URL 就能访问到相应的方法

http://.../user.html?method=updateUser -- 将被 UserController.updateUser() 处理
http://.../user.html?method=deleteUser  -- 将被 UserController.deleteUser() 处理

通过参数的方式使得 HTML 表单表现用户选择成为可能,例如把 method 参数可放在一个下拉框或隐藏域中。

使用 PropertiesMethodNameResolver 时的 Bean 配置



这种配置有点复杂,PropertiesMethodNameResolver 不仅与 SimpleUrlHandlerMapping 相仿又有重叠,而且必须把 SimpleUrlHandlerMapping  拉进来,无法使用默认的 HandlerMapping。从上面的配置我们可以明显的看出 HandlerMapping 和 MethodNameResolver 不同职责了,一个是定位 Controller,一个是定位 Method。

这时候分别用下面的 URL 来访问到相应 Controller 的方法

http://.../updateUser.html  --  将被 UserController.updateUser() 处理
http://.../deleteUser.html   --   将被 UserController.deleteUser() 处理

这里的 URL 恰巧和使用 InternalPathMethodNameResolver  时是一样的,但一定要理解其实他们的机制是一样的。

PropertiesMethodNameResolver 把事性搞这么复杂,被誉为最复杂的方法名解析器。可我还真看不出它还有什么独到之处,或值得一用的理由,同时也不难理解 Struts 的 MappingDispatchAction 鲜为人知的缘由了。


[版权声明]
本站内文章,如未特别注明,均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。
posted on 2008-10-06 14:54 隔叶黄莺 阅读(1680) 评论(2)  编辑  收藏 所属分类: Spring

Feedback

# re: Spring MVC 中的 MultiActionController 用法详解[未登录] 2008-10-07 10:24 allen
我觉得用PropertiesMethodNameResolver 相对于InternalPathMethodNameResolver 的好处在于,可以自定义和controller里方法名不一样的url mapping ,但坏处很明显必须在PropertiesMethodNameResolver 里为每一个方法都定义一个key  回复  更多评论
  

# re: Spring MVC 中的 MultiActionController 用法详解 2008-10-07 10:51 隔叶黄莺
是的,PropertiesMethodNameResolver 会让 Bean 配置过于复杂,我觉得还是像 Struts 的 DispatchAction 那样写在 URL 里(http://.../user.html?method=updateUser) 方便也直白。所以 ParameterMethodNameResolver 应该是更好的选择。

不知楼上实际应用中是怎么样的?我对 Spring MVC 尚处理研究阶段。  回复  更多评论
  


标题  
姓名  
主页
验证码 *  
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-10-06 19:58 编辑过