锁定老帖子 主题:jsplet:对Model 2模式的批判
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-03-25
jsplet模式不是model1, 不是model2, 与view结合时使用的是拉模式而不是推模式,关键思想是对象化。 在Jsp Model 2模型中, 用户的所有请求提交给Controller Servlet, 由Controller进行统一分配, 并且采用推的方式将不同的UI显示给用户。 这种推方式在很多人看来是一种优点,因为在Struts等MVC实现中具体推送的UI可以在配置文件中配置,配置完成后还可以通过一些可视化分析工具得到整个站点地图。在Model2模式中基本的访问格式为: action.do?其他参数 我本人从未应用过Model2模式,但与我们的jsplet框架对比,我认为这种推送方式在大多数情况下并不是什么优点。如果将一次web访问看作是一次函数调用,则按照Model2模式,这个函数的返回情况是不确定的,需要由一个额外的配置文件来确定。而我们知道,一个返回情况不确定的函数一般不是什么良好的设计。在我们的框架设计中,一个基本的观点是尽量将自由度暴露给实际控制它的人。实际上,在大多数情况下,页面编制人员知道应该使用哪个页面来显示数据,他们并不需要一个额外的配置文件。Jsplet使用如下的url格式: 视图jsp?objectName=模型对象名&objectEvent=响应事件名&其他参数 举一个具体的例子: http://my.com/demo_view.jsp?objectName=/@Demo&objectEvent=test demo_view.jsp是指定的显示页面, 其代码如下: <%@ include file = "/engine.jsp" %> <!-- 相当于在jsp模型中增加了一个新的变量thisObj,从而实现jsp页面的对象化 --> <c:out>${thisObj.testVar}</c:out> objectName被WebEngine映射到session中的一个对象,在demo_view.jsp中成为thisObj这个变量,这就相当于java语言中的this指针,从而实现了jsp页面的对象化。 WebEngine还将objectEvent映射到一个Action响应函数并自动调用它,具体的Action代码写在一个独立的java文件或者jsp文件中。 DemoAction.jsp <%@ include file = "/jsp_action_begin.jsp" %> <%! // // objectName映射为thisObj, objectEvent=test映射对actTest的调用 // 在这里增加一个actXXX函数之后,即可通过objectEvent=XXX来访问,不需要任何配置 public Object actTest();{ // thisObj中的变量可以在视图中使用 thisObj.set("testVar","hello");; return success();; } // 如果存在actBeforeAction函数,则该函数在所有action函数之前调用 public Object actBeforeAction();{ return success();; } // 如果存在actAfterAction函数,则该函数在所有action函数之后调用 public Object actAfterAction();{ return success();; } %> <%@ include file="/jsp_action_end.jsp" %> 在Jsplet框架中只需要注册对象,而不需要单独注册每个action。 register.jsp <% WebEngine.registerType("Demo", new WebActionType("/demo/action/DemoAction.jsp");,pageContext);; %> 与Jsplet框架对比,Model2是对action的建模而不是对object的建模,即它相当于将objectName,objectEvent和view.jsp绑定在一起定义为一个访问点action.do,绑定过程中需要一个配置文件来固化view.jsp和action之间的联系。因此, Model2并没有完全分离view和model,它隐含假定着objectName只具有一个objectEvent, 并且绑定了一个具体的view(出错页面除外)。 例如, 我们需要两个不同的view来显示同一个数据,则在Model2程序中可能需要配置两个独立的访问点,而在我们的框架中只需要使用两个不同的url: a_view.jsp?objectName=/@Demo&objectEvent=test b_view.jsp?objectName=/@Demo&objectEvent=test 同样的web程序甚至可以在前台通过XMLHTTP方式来调用而不需要额外配置! 在Jsplet框架中采用的是对象化的方式而不是Action化的方式,因此存在着多种面向对象的扩展,而所有的扩展都直接体现在url格式的细化上,一切都在阳光下。 在Jsplet中objectName是WebObject的名称,在全系统内唯一,其格式定义为: objectScope@objectType$objectInstanceId 1. 对象类型objectType 我们需要注册的是对象类型而不是完整的对象名,一个对象类型可以对应于无数个完整的对象名,例如我们注册了Demo类型的WebObject, 则objectName=/@Demo和objectName=/left/@Demo对应的处理文件都是DemoAction.jsp。 2. 对象生命周期控制objectScope objectScope为WebObject所在的域,其格式符合Unix路径命名规范。JSP模型本身支持一些预定义的对象域,包括page, request, session, application等。但为了能够反映现实世界中的对象组织结构,对象域必须是允许自定义的。objectScope被组织成一个树形结构,这是一个基本的控制结构,其控制策略为 同时存在的对象域之间必须存在线性序关系(order) 当系统访问某一对象时,如果该对象所在的对象域不能和现有对象的域处在同一"路径"下(即当对象域之间不能建立父子关系时),系统就会自动销毁不兼容路径分支下的所有对象。 这种精细的控制策略保证了系统的可扩展性,因为模型上可以保证始终只有一部分对象被创建。 对象转移 系统动作 /main/@MyObject ==> /main/left/@OtherObject 无 /main/left/@OtherObject ==> /main/@MyObject 无 /main/left/@OtherObject ==> /main/left/@MyObject 无 /main/left/@OtherObject ==> /main/right/@MyObject 自动销毁/main/left子域下的对象,如/main/left/@OtherObject 3. 对象实例标识 objectInstanceId 如果在某一对象域中需要包含多个同一类型的对象,可以通过objectInstanceId来加以区分,这样在同一个页面上我们可以使用多个同样类型的对象。 Jsplet中另外一个扩展是通过事件路由来支持jsp子页面的对象化。例如 http://my.com/demo_main.jsp?objectName=/@Main&eventTarget=/@Sub&objectEvent=test 如果指定了eventTarget参数,则objectEvent由eventTarget对应的对象来响应。 在jsp文件内部我们可以通过include语法来引入子对象,例如 <jsp:include page="sub_view.jsp?objectName=/@Sub" /> (注:我不是非常清楚Tapestry具体是如何实现对象化的,熟悉Tapestry的朋友可以介绍一下) 在Jsplet中可以通过配置文件来支持对Action的interception, 例如 <factory> <listener-filter class="global.LogFilter" /> <post-listener class="global.CommonActions"/> <type name="Demo"> <!-- 如果未指定object, 则缺省为WebObject类型 --> <object class="demo.MyWebObject" /> <listener> <filter event="query*|select*" class="demo.LogFilter" /> <url-listener url="/demo/DemoAction.jsp" /> <url-listener url="/demo/DemoAction2.jsp" /> </listener> </type> </factory> 在上面这个配置文件中,DemoAction.jsp和DemoAction2.jsp是chain关系,即事件响应的传播模型中,如果event没有被标记为stopPropagation,就会传递到下一个listener。 综上所述,可以看到在目前多变的需求环境下,Model 2已不是一种非常完善的Web程序模式,一些重要的设计需求在Model 2模式的推方式中很难得到合适的表达。 关于jsplet框架的设计理论可以进一步参见我的blog: http://canonical.blogdriver.com 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-03-25
MVC的一个潜在好处 是性能。(这个潜在好处能否发挥,就看MVC框架本身的Action管理机制了)
MVC只定义一个 DispatchServlet,用户逻辑入口都是Action。 Action一般都是比Servlet 轻量的Class。 MVC框架可以自行管理Action的生命周期。 JSP要编译为Servlet,而Servlet是Web Server管理的相对比较昂贵的资源。Web Server能够管理的Servlet的个数,并不是无限的。 只有在成千个JSP页面的情况下,这个问题才比较明显。一般情况下,不用考虑这个方面。:-) |
|
返回顶楼 | |
发表时间:2005-03-25
jsp编程无非 页面提交-->业务过程--〉结果页面 的流程
业务过程在jsp里头大抵就是mode1,统一扔到了servlet里就成了mode2 你的框架里面,业务过程到底在什么地方实现?又通过什么模式由页面调用? 看你的例子好像是在jsp中直接写死业务类的类名(或者jsp页面名称?) 还是另有一个管理器允许页面通过某种手段直接获得指定的业务类 如果业务类类名要更动会不会导致几十上百个jsp页面的更动? 如果是指向jsp页面,oop的全套把式岂不是都用不上了? 还是给一个完整的login之类的例子比较好 连login.jsp,success.jsp,error.jsp带UserLogin具体操作,等等 这样大家都可以看得清楚一点 |
|
返回顶楼 | |
发表时间:2005-03-25
引用 我们知道,从客户端提交过来的东西都是可以伪造的.所以一但认识到有问题,就会加密,加密又引起调用参数的麻烦.就会做到JSP里,但是做在JSP里不方便.当然不如XML了灵活了,这就是model2.
这是没有道理的,程序的安全性是由model层控制的,view层的关键数据由model层而来,如果需要绑定的话,直接在jsp中增加一句判断就可以了。 引用 mvc正式model2
model2最多只能是MVC的一种,怎么等价于这个概念呢。你可能还不太习惯jsplet中的思想。 引用 或许jsplet的美工人员就是程序员? 要在URL中控制程序的转向?应该由程序员做的事,交给美工?
在前台总是要写代码的,用model2难道就不需要知道调用什么功能了吗。当然在我们的平台中在jsp层还有模板机制专门面向美工。在一般情况下我们是把js隔离到一个层中,改模块调用的时候是改js文件而不是模板文件的。 引用 作为MVC,专门有个控制层管理,集中起来管理,方便.
Model2要求这个集中配置文件很方便吗?在我们开发的大型系统中,很多人独立开发,增加一个小的action需要改全局配置??? |
|
返回顶楼 | |
发表时间:2005-03-25
MVC2没有错,只是你使用的框架问题(有你本身的问题,例如,不熟练,也有可能本身是框架的缺陷)(现在大部的框架都可以将配置文件分开来写)
MVC2的做法,不一定是推,只是在实现的时候,我们往往选择了推,其实用拉页面的方法,更简单. 推的做法是程序员(亦有可能是其它的人)写配置:缺点就是配置文件已经写死了,并不能灵活改变.但也讲一点个人项目实践,其实真正的可变的并不多,可以讲几乎是没有. 拉的做法是客户写配置(单单指楼主的框架类型):后面的参数就想当于配置了,还有就是可能你对jsp不太了解,有一些页面放置的结构不一样,你客户端未必能访问(这个我就不多讲了,如果你还问是哪些页面不能访问的话,你就自己看一下书吧,加强一下).服务器端的配置文件能够统一访问的路径,但像这种拉的方式,却可要麻烦了,还有写一大堆的参数,而且还要暴露一些本不应该让客户知道的东西.还有就是一是不旦有一些东西改变(例如模块名),就改写你(因为你不是集中管理的) 其实往往V与M是偶合的,不能分开的,楼主为什么要用拉的方式呢? 再讲MVC,不想讲了,自己看书吧...问人吧.. MVC最重要的是什么就是把逻辑,显示,控制分开,只要你做到了这点,就是MVC |
|
返回顶楼 | |
发表时间:2005-03-25
引用 Model2要求这个集中配置文件很方便吗?在我们开发的大型系统中,很多人独立开发,增加一个小的action需要改全局配置??? 难道你的改了,不用改配置?你的东西一样不能克服这个缺点 MVC2模式与MVC1最大的区别就是加强了控制器(统一了转发等). 其实像你这种框架也可以讲是MVC2,只不过与一般的框架有点不同而罢了(实现不同). |
|
返回顶楼 | |
发表时间:2005-03-25
看来看去,本质还是Model 2
|
|
返回顶楼 | |
发表时间:2005-03-25
有些人自己没有设计过框架,所以总把Model2等价于MVC,这是错误的看法。
引用 MVC2的做法,不一定是推,只是在实现的时候,我们往往选择了推,其实用拉页面的方法,更简单.
Model2就是推方法,如果不是,那就不是Model2而是别的MVC。 Jsplet可以退化为Model2,即采用如下访问格式: http://my.com/engine.jsp?objectName=XX&objectEvent=xx 引用 可能你对jsp不太了解,有一些页面放置的结构不一样,你客户端未必能访问(这个我就不多讲了,如果你还问是哪些页面不能访问的话,你就自己看一下书吧,加强一下).
真是滑天下之大稽,我自己写过server的。 引用 难道你的改了,不用改配置?你的东西一样不能克服这个缺点
在Action.jsp文件中增加一个actXX函数,则在页面上即可通过objectEvent=XX来访问了。这就相当于是WebService调用。 引用 是不旦有一些东西改变(例如模块名),就改写你(因为你不是集中管理的)
仍然是集中改写的,我说过了,在前台控制层。只是不是全局集中而是模块集中。 Jsplet最关键的特征是对象化,但是缺省使用了拉模式,这是与Model2不同的地方,因为推模式隐含的假设是结果是不确定的,但绝大多数情况下完全是确定的情况。 引用 但也讲一点个人项目实践,其实真正的可变的并不多,可以讲几乎是没有.
引用 MVC最重要的是什么就是把逻辑,显示,控制分开,只要你做到了这点,就是MVC
这句话有点道理,但情况可以更复杂。另外说到底,MVC只是一种模式,更复杂的模式是什么,你明白吗 引用 往往V与M是偶合的,不能分开的,楼主为什么要用拉的方式呢?
参考上面的分离的说法,这个说法是不是自相矛盾?举个例子,我需要显示列表 listA.jsp?objectName=xxx&objectEvent=yyy 如果我想要以不同的方式显示这个列表 listB.jsp?objectName=xxx&objectEvent=yyy 如果用面向action的方式 actionA.do?xxx actionB.do?yyy 谁知道这两个action是相关的? Model2的一般实现中没有采用对象化的方法所以无法捕获这种相关性。 |
|
返回顶楼 | |
发表时间:2005-03-25
引用 1.退化, 就是有违程序设计原则!
比如把控制层暴露在网页上. 不要被你已有的知识蒙蔽了眼睛。退化指的是在复杂性层次上的降级。不要认为分发页面就是控制层。用户做原型的时候就知道页面是怎么分发的。网页仍然是需要程序员参与的。美工做的是模板的部分。如果要屏蔽点击按钮后页面的去向,有很多种办法。action的名字难道比页面文件名本身更稳定的吗。 引用 jsplet是MODEL2一点不假,
再说一遍, Model2是推方式。 引用 ACTION改为WEBACTION. 但不知道action放在JSP里有什么优点.
很简单,可以动态修改,不需要重起服务器。当然action也可以放到java文件中,代码拷贝过去就可以了,两种方式都支持。 引用 action.do?objectName=A
action.do?objectName=B 但是动态action只用作控制层,所以符合程序设计原则. 在这种方式下框架管理的action而不是对象。工作总是分为框架做和程序做。到底框架做什么,程序做什么。 引用 还有你的参数中的objectName只是一个字串,只是参数的变种,最多几个参数并在一起,最后用正则表达试分开.去调相应的类和方法.我不认为这有多大意义.
那说起来 url就是一个整体,我们可以用正则表达式将queryString分离出去。识别出需要把握的概念就是对象化,对象化之后才考虑更深层次的控制问题。 jsplet中最重要的设计概念是对象化,当然使用拉方式是能够对象化的前提。 真正重要的以下部分 1. 注册对象名 ==> 注册对象类型 2. 对象生命周期管理 3. 对象事件路由 现在我要在一个页面上同时包含两个现成的子模块,在Model2模型中怎么做? |
|
返回顶楼 | |
发表时间:2005-03-25
引用 canonical,那个JSPLET是你设计的么?
当然,开发最初版本的时候,struts还不流行,所有的概念基本都是当时定下来的,除了interceptor是在AOP概念出现之后。 引用 不过楼主有创新思想,而且有程序员的天质.这是值得肯定的!
你挺有意思的,我做系统设计很多年了 |
|
返回顶楼 | |