锁定老帖子 主题:spring3mvc与struts2比较
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-25
slaser 写道 第一,没看出来spring的aop拦截限制了什么应用了,我的输入输出都在参数和返回值上,为什么还需要其他拦截,你能拿出什么实际的例子让spring mvc做起来很难受的么?另外,说起spring aop天然支持aop有什么错,spring aop的后面是aspectj,对于领域对象的注入和拦截也是可以靠aspectJ搞定的。 第二,难道Spring MVC执行层次不多,定制化不强?可插入url的解析,多种view的支持,Spring Webflow,Security集成被你无视了。 第三,不认为Struts2在技术上完胜,struts2走了和Spring MVC不同的路,这个才是关键,而我觉得它现在是个半成品。论优雅,可以去学习JSF. 拦截器拦截的内容仅仅限制于参数和返回值是一件令人头疼的事情,这就意味着你的拦截器代码不可避免的要和这些内容去打交道。也就是说,一旦我要在里面加一些特殊的逻辑,比如根据参数或者返回值中的某个字段进行逻辑判断,就会使得你的拦截器依赖于特定的切面而变得毫无意义。 @RequestMapping(value="/whitelists") public String index(ModelMap map){ Account account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId()) ; List<Group> groupList = groupManager.findAllGroup(account.getId()) ; map.put("account", account); map.put("groupList", groupList); return "/group/group-index" ; } //@ResponseBody ajax响应 @RequestMapping(value="/whitelist/{whiteListId}/del") @ResponseBody public String delete(@PathVariable Integer whiteListId){ whiteListManager.deleteWhiteList(whiteListId) ; return "success" ; } 在这其中我们可以看到: map.put("account", account); map.put("groupList", groupList); 这两句话纯粹就是多余的。一共5行code,有2行在为返回输出做准备。你还能厚着脸皮说SpringMVC解放了你的生产力? 在Struts2中,代码就会变成这样: Account account; List<Group> groupList; public String index(){ account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId()) ; groupList = groupManager.findAllGroup(account.getId()) ; return "/group/group-index" ; } 你所需要关注的,只是你的业务逻辑调用,而无需关心返回到底是什么名称,更不用提什么显示调用map.put这种恶心的代码了。 再问,你能用你所谓Spring的AOP把map.put这两行code给省略了嘛?所有的返回的内容都是局部变量,你去拦截啊?无能为力了吧。 至于说到什么url解析,多view的支持,SpringMVC的支持也仅仅限于支持而已,这些所谓的支持,成熟的Web层框架全部都有。所谓的Annotation带来的配置简化,本身就是一个伪命题。@RequestMapping(value="/whitelist/{whiteListId}/del")这种看上去优雅的实现,其实带来的问题却是致命的。这一点我很早就已经指出过。你可以翻看我以前的帖子。 SpringMVC充其量也就是一个简单的Web层的Mapping工具,要谈到综合性的Web层解决方案,它还差得很远。Struts2本身的设计思想和实现是所有MVC框架中最先进的。它也有很多问题,但是至今为止我还没有找到足够的证据来说明它的问题。所以希望大家在抱怨的同时,仔细想想你的观点是否真的站得住脚。 |
|
返回顶楼 | |
发表时间:2010-06-25
最后修改:2010-06-25
我倒觉得# Account account;
# List<Group> groupList; 这两个属性很恶心。 为什么要用AOP来省掉那两行代码呢? 你通常用拦截器做什么事情? 不太明白你的意思。 扩展点多确实没什么好炫耀的,足够、实用就好了。 评价一个框架好坏主要还是看开发效率、是否简洁、配置是否一致、符合直觉。 Struts2有webflow类似的插件么? |
|
返回顶楼 | |
发表时间:2010-06-25
daquan198163 写道 我倒觉得# Account account;
# List<Group> groupList; 这两个属性很恶心。 为什么要用AOP来省掉那两行代码呢? 你通常用拦截器做什么事情? 不太明白你的意思。 扩展点多确实没什么好炫耀的,足够、实用就好了。 评价一个框架好坏主要还是看开发效率、是否简洁、配置是否一致、符合直觉。 Struts2有webflow类似的插件么? 一共5行代码,有2行和你关注的内容无关,你认为这两行代码有存在的必要吗?这就和你在Service层去显示调用transaction.begin()或者transaction.commit()有什么分别? 在Action中使用属性,使得一个Action更像一个JavaBean,可以使得测试更加容易。同时,这才是真正的面向对象的编程,一个拥有属性和方法的类,而不是只有方法。如果我们关注一下Spring的主要编程思想,Spring中的所有的Bean,其实都是在往具备丰富属性加方法的趋势发展的。Struts2的Action天然就是一个JavaBean,你居然能够说出这两个属性很恶心的话来,我不能理解你的想法。 拦截器做什么事情?我用拦截器做的事情太多了。拦截器的一个很大的作用就是精简与业务逻辑调用无关的恶心代码。至于你说的是否简洁、配置是否一致、是否符合直觉,我更加不能理解了,从任何角度来说,Struts2都能满足你的这3点。 Struts2有很多插件,官方网站上你可以查找一下。 |
|
返回顶楼 | |
发表时间:2010-06-25
最后修改:2010-06-25
daquan198163 写道 我倒觉得# Account account; # List<Group> groupList; 这两个属性很恶心。 确实恶心,都不知道用来输入,还是输出的,也不知道在哪个方法里面调用。 当你把多个功能写到一个action里面的时候,实例变量带来的只是混乱。 |
|
返回顶楼 | |
发表时间:2010-06-25
downpour 写道 一共5行代码,有2行和你关注的内容无关,你认为这两行代码有存在的必要吗?这就和你在Service层去显示调用transaction.begin()或者transaction.commit()有什么分别? 在Action中使用属性,使得一个Action更像一个JavaBean,可以使得测试更加容易。同时,这才是真正的面向对象的编程,一个拥有属性和方法的类,而不是只有方法。如果我们关注一下Spring的主要编程思想,Spring中的所有的Bean,其实都是在往具备丰富属性加方法的趋势发展的。Struts2的Action天然就是一个JavaBean,你居然能够说出这两个属性很恶心的话来,我不能理解你的想法。 拦截器做什么事情?我用拦截器做的事情太多了。拦截器的一个很大的作用就是精简与业务逻辑调用无关的恶心代码。至于你说的是否简洁、配置是否一致、是否符合直觉,我更加不能理解了,从任何角度来说,Struts2都能满足你的这3点。 Struts2有很多插件,官方网站上你可以查找一下。 你所谓的省掉两行代码,只不过是把那两个值付给了action的属性而已,而且它们也不是“不需要关注的内容”,它们恰恰是这里的业务逻辑, transaction.begin()和commit()显然不属于业务逻辑,区别非常的大,一黑一白。 如果面向对象让我的日子难过,我会毫不犹豫的丢掉面向对象。我们还是少搞一些宗教,多一些务实的好。 我当然知道拦截器做什么,但我看不出有什么拦截器需要做的工作会由于只能拦截参数、返回值而变得不能做了,所以,还是请你列举出典型场景。 前面也说了,那两行代码属于业务逻辑,跟拦截器没什么关系,也不需要劳驾拦截器去精简,并且ww那个做法也没有精简。 我说的“是否简洁、配置是否一致、是否符合直觉 ”指的是ww/struts2把局部变量搞成实例变量这种做法。 |
|
返回顶楼 | |
发表时间:2010-06-25
downpour 写道 一共5行代码,有2行和你关注的内容无关,你认为这两行代码有存在的必要吗?这就和你在Service层去显示调用transaction.begin()或者transaction.commit()有什么分别? 有必要的,我确实关注需要输出那些,不要输出什么内容。动不动输出整个Action的实例变量给View调用,让我在写View的时候很迷茫。 downpour 写道 在Action中使用属性,使得一个Action更像一个JavaBean,可以使得测试更加容易。同时,这才是真正的面向对象的编程,一个拥有属性和方法的类,而不是只有方法。如果我们关注一下Spring的主要编程思想,Spring中的所有的Bean,其实都是在往具备丰富属性加方法的趋势发展的。Struts2的Action天然就是一个JavaBean,你居然能够说出这两个属性很恶心的话来,我不能理解你的想法。 。。。 Struts2有很多插件,官方网站上你可以查找一下。 同意你对struts的action更oo的说法,确实是这么回事,spring mvc和struts1的action就是过程式的处理。所以我说spring mvc和struts2是2个方向,我不觉得spring mvc的做法更糟糕。 |
|
返回顶楼 | |
发表时间:2010-06-25
对于楼上两位的论调,我感觉非常遗憾。Java发展到现在,还有人可以堂而皇之的告诉我,显示调用map.put,是业务逻辑的一部分,为了分清楚所谓的输入输出,宁可放弃OO。
到底是使用类的实例变量还是局部变量,你可以从Spring的设计思想中得出结论。你们说来说去无非是说实例变量让你们分不清输入还是输出。这样的伪问题真是不知道令人如何回答。我曾经见过有人是这样用Struts2的Action的:在一个Action中,放一个Map专门来做输入,再专门放一个Map来做输出。我不知道这样是否能解决两位的问题。但是我想告诉你,无论从哪个角度来说,使用类似SpringMVC中的ModelMap来进行返回输出,都是很多年前的思路(这与Struts1中的FormBean是一个概念)。你仔细想想,你是否真的要知道输入和输出?这对你意义真的有那么大嘛? 你们所谓的类的实例变量的泛滥,更加是一个伪命题。这纯粹是你们在项目中没有正确规划Action与URL的mapping关系造成的。这就取决于你们团队的水平问题了,至少在我们的团队中,还从来没有人向我抱怨过这样的问题。 拦截器能做什么?你认为丰富的执行层次没什么了不起。我可以告诉你,在我们的团队中,丰富的执行层次给我们带来了极大的扩展空间。我来给你举个简单的场景。 在一个典型的具备多条件查询的页面中,我们尝试这样来构建我们的JSP: <input type="text" name="eq.user.code" /> <input type="text" name="gt.user.birthday" /> <input type="text" name="lt.user.birthday" /> 看到这样的input名称了嘛?我们只要使用一个拦截器,就可以很轻松的根据这些name/value的值,动态构建一个SearchComponent到Struts2的Action中,并将这个SearchComponent作为参数传到后台,调用通用的DAO方法就可以完成查询,而省略了所有的null值判断,动态拼接SQL的工作。 当这样的多条件查询的页面在一个系统里面有几十个甚至是上百个的时候,你就会发现Struts2拦截器的作用,是能够极大的解放我们的生产力的。 这些可以说只是冰山的一角,我们甚至使用Struts2的拦截器来做一切与Http传递参数相关的事情。比如说,一个导入功能,通过http上传csv文件来实现。通过使用Struts2的拦截器,在Struts2的Action中你甚至看不到File的影子,被我们写的拦截器拦截后,通过csv模板的解析,将csv文件的内容转化为对象传递到Action中去了。 这样的业务场景太多,没必要一一列举了。 我想有关这类讨论应该告一个段落,我也不打算说服大家说Struts2有多好,因为实际上每个应用的使用场景都不同,只希望大家在Web层框架选择时,多多思考一些与应用相关的事情,而不是去讨论框架本身,框架是死的,使用框架的人是活的,希望大家在应用层面多总结一些最佳实践,而不是报怨框架的好坏。 |
|
返回顶楼 | |
发表时间:2010-06-25
最后修改:2010-06-25
对于楼上两位的论调,我感觉非常遗憾。Java发展到现在,还有人可以堂而皇之的告诉我,显示调用map.put,是业务逻辑的一部分,为了分清楚所谓的输入输出,宁可放弃OO。
既然是基于请求的框架,那么把输入输出分清楚是一个最最基本的要求,这都不行的话还搞啥球的OO 到底是使用类的实例变量还是局部变量,你可以从Spring的设计思想中得出结论。你们说来说去无非是说实例变量让你们分不清输入还是输出。这样的伪问题真是不知道令人如何回答。我曾经见过有人是这样用Struts2的Action的:在一个Action中,放一个Map专门来做输入,再专门放一个Map来做输出。我不知道这样是否能解决两位的问题。但是我想告诉你,无论从哪个角度来说,使用类似SpringMVC中的ModelMap来进行返回输出,都是很多年前的思路(这与Struts1中的FormBean是一个概念)。你仔细想想,你是否真的要知道输入和输出?这对你意义真的有那么大嘛? 这样当然不行,换成map也还是实例级别的变量,多个方法的变量还是参合在一起,换汤不换药。 spring的设计思想说明不了什么问题,因为spring是个透明的中间层框架,而Struts2是不透明的MVC框架。 还是那句话,既然是基于请求的框架,那么把输入输出分清楚是一个基本要求。 你们所谓的类的实例变量的泛滥,更加是一个伪命题。这纯粹是你们在项目中没有正确规划Action与URL的mapping关系造成的。这就取决于你们团队的水平问题了,至少在我们的团队中,还从来没有人向我抱怨过这样的问题。 是呀,只要足够的聪明和小心,我们可以驾驭任何难用的框架。但是容易犯的错误最终一定会变成泛滥的错误。 你们团队没人抱怨只能说明你们NB,但不代表Struts2的这个设计不SB 拦截器能做什么?你认为丰富的执行层次没什么了不起。我可以告诉你,在我们的团队中,丰富的执行层次给我们带来了极大的扩展空间。我来给你举个简单的场景。 丰富的执行层次当然重要,但拦截器链实在不是一个聪明的实现,最大的问题就是阶段含义和分工不明确,跟把所有变量都堆在实例级别是一样的错误。 像SpringMVC这样,通过TemplateMethod模式,提供各个阶段的生命周期回调才对路 在一个典型的具备多条件查询的页面中,我们尝试这样来构建我们的JSP: <input type="text" name="eq.user.code" /> <input type="text" name="gt.user.birthday" /> <input type="text" name="lt.user.birthday" /> 看到这样的input名称了嘛?我们只要使用一个拦截器,就可以很轻松的根据这些name/value的值,动态构建一个SearchComponent到Struts2的Action中,并将这个SearchComponent作为参数传到后台,调用通用的DAO方法就可以完成查询,而省略了所有的null值判断,动态拼接SQL的工作。 当这样的多条件查询的页面在一个系统里面有几十个甚至是上百个的时候,你就会发现Struts2拦截器的作用,是能够极大的解放我们的生产力的。 这个可以有啊,无非是 参数填充、criterial、通用DAO、validation,不妨拿出来分享一下吧,我帮你弄个springmvc版的 这些可以说只是冰山的一角,我们甚至使用Struts2的拦截器来做一切与Http传递参数相关的事情。比如说,一个导入功能,通过http上传csv文件来实现。通过使用Struts2的拦截器,在Struts2的Action中你甚至看不到File的影子,被我们写的拦截器拦截后,通过csv模板的解析,将csv文件的内容转化为对象传递到Action中去了。 呵呵,我觉得这种变魔术的实现方式是自作聪明,我在action里调用helper解析csv多直接啊,免得不熟悉的人到action里找不到file,把简单事情搞复杂很过瘾么? 这样的业务场景太多,没必要一一列举了。 我想有关这类讨论应该告一个段落,我也不打算说服大家说Struts2有多好,因为实际上每个应用的使用场景都不同,只希望大家在Web层框架选择时,多多思考一些与应用相关的事情,而不是去讨论框架本身,框架是死的,使用框架的人是活的,希望大家在应用层面多总结一些最佳实践,而不是报怨框架的好坏。 框架就是固化了的最佳实践 |
|
返回顶楼 | |
发表时间:2010-06-25
楼上的这位同学,讨论中止,我认为你的水平还不足以和我讨论。希望你首先明白什么才是OO,什么才是优雅。我不乐意和一个毫无是非观念的人讨论下去,这毫无意义。
|
|
返回顶楼 | |
发表时间:2010-06-25
那您就耐心赐教一下呗,毕竟都一起打过球的
|
|
返回顶楼 | |