论坛首页 Java企业应用论坛

jsplet:对Model 2模式的批判

浏览 17623 次
精华帖 (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
   发表时间:2005-03-25  
MVC的一个潜在好处 是性能。(这个潜在好处能否发挥,就看MVC框架本身的Action管理机制了)
MVC只定义一个 DispatchServlet,用户逻辑入口都是Action。
Action一般都是比Servlet 轻量的Class。
MVC框架可以自行管理Action的生命周期。

JSP要编译为Servlet,而Servlet是Web Server管理的相对比较昂贵的资源。Web Server能够管理的Servlet的个数,并不是无限的。
只有在成千个JSP页面的情况下,这个问题才比较明显。一般情况下,不用考虑这个方面。:-)
0 请登录后投票
   发表时间:2005-03-25  
jsp编程无非 页面提交-->业务过程--〉结果页面  的流程
业务过程在jsp里头大抵就是mode1,统一扔到了servlet里就成了mode2

你的框架里面,业务过程到底在什么地方实现?又通过什么模式由页面调用?

看你的例子好像是在jsp中直接写死业务类的类名(或者jsp页面名称?)
还是另有一个管理器允许页面通过某种手段直接获得指定的业务类

如果业务类类名要更动会不会导致几十上百个jsp页面的更动?
如果是指向jsp页面,oop的全套把式岂不是都用不上了?

还是给一个完整的login之类的例子比较好
连login.jsp,success.jsp,error.jsp带UserLogin具体操作,等等
这样大家都可以看得清楚一点
0 请登录后投票
   发表时间: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需要改全局配置???
0 请登录后投票
   发表时间:2005-03-25  
MVC2没有错,只是你使用的框架问题(有你本身的问题,例如,不熟练,也有可能本身是框架的缺陷)(现在大部的框架都可以将配置文件分开来写)

MVC2的做法,不一定是推,只是在实现的时候,我们往往选择了推,其实用拉页面的方法,更简单.

推的做法是程序员(亦有可能是其它的人)写配置:缺点就是配置文件已经写死了,并不能灵活改变.但也讲一点个人项目实践,其实真正的可变的并不多,可以讲几乎是没有.

拉的做法是客户写配置(单单指楼主的框架类型):后面的参数就想当于配置了,还有就是可能你对jsp不太了解,有一些页面放置的结构不一样,你客户端未必能访问(这个我就不多讲了,如果你还问是哪些页面不能访问的话,你就自己看一下书吧,加强一下).服务器端的配置文件能够统一访问的路径,但像这种拉的方式,却可要麻烦了,还有写一大堆的参数,而且还要暴露一些本不应该让客户知道的东西.还有就是一是不旦有一些东西改变(例如模块名),就改写你(因为你不是集中管理的)

其实往往V与M是偶合的,不能分开的,楼主为什么要用拉的方式呢?

再讲MVC,不想讲了,自己看书吧...问人吧..

MVC最重要的是什么就是把逻辑,显示,控制分开,只要你做到了这点,就是MVC
0 请登录后投票
   发表时间:2005-03-25  
引用

Model2要求这个集中配置文件很方便吗?在我们开发的大型系统中,很多人独立开发,增加一个小的action需要改全局配置???


难道你的改了,不用改配置?你的东西一样不能克服这个缺点

MVC2模式与MVC1最大的区别就是加强了控制器(统一了转发等).

其实像你这种框架也可以讲是MVC2,只不过与一般的框架有点不同而罢了(实现不同).
0 请登录后投票
   发表时间:2005-03-25  
看来看去,本质还是Model 2
0 请登录后投票
   发表时间: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的一般实现中没有采用对象化的方法所以无法捕获这种相关性。
0 请登录后投票
   发表时间: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模型中怎么做?
0 请登录后投票
   发表时间:2005-03-25  
引用
canonical,那个JSPLET是你设计的么?

当然,开发最初版本的时候,struts还不流行,所有的概念基本都是当时定下来的,除了interceptor是在AOP概念出现之后。

引用
不过楼主有创新思想,而且有程序员的天质.这是值得肯定的!

你挺有意思的,我做系统设计很多年了
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics