锁定老帖子 主题:Portal展现机制研究
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-08-31
看来BlueDavy正在做一个相关的产品,可否把在“View层”你们所考虑的的需求罗列出来,我前面提到的需求过于简单。根据Portal产品的特点,需求方面应该要综合考虑最终用户、管理员、开发人员。
我认为针对需求来讨论设计会更加有效。 |
|
返回顶楼 | |
发表时间:2004-09-01
flyisland 写道 事实上这里是一个“创建者”模式的问题,谁负责调用(创建)Portlet,谁就要有“创建哪些?创建多少个?”这些信息。当PageTag调用(创建)Portlet的时候,PageTag就需要知道当前需要创建那些Portlet,而且对于不同的Page实例答案是不一样的。引入组件树的概念重点在于:把创建责任独立出来,由一个引擎在遍历组件树的过程中负责调用各个组件的显示,尽量减少JSP之间的调用。这样负责显示的JSP页面更加干净,而且允许非常灵活的组件树结构。
组建树的概念同意,不过创建和调用就是两码事了。 |
|
返回顶楼 | |
发表时间:2004-09-01
intolong 写道 flyisland 写道 事实上这里是一个“创建者”模式的问题,谁负责调用(创建)Portlet,谁就要有“创建哪些?创建多少个?”这些信息。当PageTag调用(创建)Portlet的时候,PageTag就需要知道当前需要创建那些Portlet,而且对于不同的Page实例答案是不一样的。引入组件树的概念重点在于:把创建责任独立出来,由一个引擎在遍历组件树的过程中负责调用各个组件的显示,尽量减少JSP之间的调用。这样负责显示的JSP页面更加干净,而且允许非常灵活的组件树结构。
组建树的概念同意,不过创建和调用就是两码事了。 应该说类似“创建者”模式的概念,主要是一个责任分配的问题。 |
|
返回顶楼 | |
发表时间:2004-09-01
flyisland 写道 我认为针对需求来讨论设计会更加有效。
恩,很同意这话,没有需求何来设计,在做设计前首先需要知道的也就是所做的东西的目的到底是什么,目标是什么,这其实同样也是TDD的思想,扯远了一些,呵呵... 需求的话我首先说一下最终用户的需求吧,这从是我们所做的一个项目抽取的,但由于所做的是政府项目,所以可能和企业的会有些不同 政府项目而言由于其用户面广而且意见频繁的不同使得页面改动很频繁,但由于系统是给公务员用的,影响到政府形象,所以在页面上其实是没有什么个性化的,只是有不同的页面类型而已,比如领导需要有领导的页面,普通公务员有普通公务员的界面,办公室又需要办公室的页面,由于他们没有个性化定制这方面的需求,下面描述的需求基本都是根据他们的使用情况转化为技术方面而言的一些需求: 1. 需要提供灵活的页面类型机制,可创建各种不同的页面类型,并由用户继承 2. 需要提供灵活的页面布局方式,方便用户频繁变化的需求 3. 同样为了满足用户频繁变化的需求,View层需要有Skin的概念 4. 页面的组织形式需要多种多样,并可轻松转变,如本来是一列按钮形式的布局处需要可换成诸如树状等结构,并且需要与权限结合 就做政府项目而言,在View层他们不会有什么明确的需求,只是会一会说我要这么做,然后过了一会又会变成要那样做,比如之初页面是两栏,突然他会要变成三栏,然后样式也是要不断的改,相对来讲View层的灵活的机制诸如个性化定制真正用的人反而是管理员,由管理员根据用户的需求直接配置出用户所期待的页面,用户直接继承该种页面类型,View层的需求也就是为了满足用户不断变化的需求而形成的。 |
|
返回顶楼 | |
发表时间:2004-09-01
flyisland 写道 应该说类似“创建者”模式的概念,主要是一个责任分配的问题。
恩,同意这话,View层之所以要做分层其实就是OO的概念,抽出来的每个层次只负责该层次的功能,比如Layout层只负责控制页面的布局,而Portlet只负责页面的具体一个小的应用模块,Skin层只负责页面的样式 各层的划分也就使得系统的改动尽量少的影响到其他层次,但由于View层不同于Model层,它需要通过和View模板结合共同完成功能,这点就使得View层的OO在一定程度上来讲难于Model层。 |
|
返回顶楼 | |
发表时间:2004-09-01
看了BlueDavy的PPT,期待BlueDavy的作品。:-)
谢谢flyisland提供的WebLogic Portal中文帮助文档。我把英文的也列在下面。 http://e-docs.bea.com/workshop/docs81/doc/en/core/index.html http://e-docs.bea.com/wlp/docs81/index.html 关于WebLogic Portal的“组件树”,主要是通过renderChild tag实现的。 for (int i = 0; i < size; i++); { PlaceholderPresentationContext child = (PlaceholderPresentationContext); children.get(i);; %> <td width="100%"><render:renderChild presentationContext="<%= child %>"/></td> 其中的PresentationContext有一个public List getChildren()方法,返回一个PresentationContext列表,这样构成一个树形结构。 我前面给出的各种portal(bea, liferay, jetspeed)的 layout jsp,是 最终用户 进入到 my portal 看到了的第一个页面。 (1)最终用户访问my portal页面。 (2)最终用户login到my portal里面。 (3) Portal系统把用户自订制的Portlets,根据用户选择的Layout, skin显示出来。这个时候,就要用到我上面列出的各种layout.jsp。 从上面列出的bea, liferay, jetspeed的 layout jsp,我们可以看出,所有的Portal实现,都无可避免地需要在layout jsp里面调用for 循环,遍历用户订制的Portlets,然后显示出来。 为什么说,这个jsp里面的for循环是没有办法避免的? (1) 首先,这个for循环是肯定要存在的 (在sun portal layout里面是forEach tag)。 (2) 这个for 循环只能存在于两个地方,或者在jsp里面,或者在tag code里面。 我前面给出的猜测,就把for写在了page tag code里面,造成了html布局元素固定在Page tag里面,使用不够灵活。 所以,我们可以看到,所有的Java Portal都不约而同地用 jsp 作为 layout,而且都直接用 for (或forEach tag)来遍历 portlets. 这里还有一个结论,velocity, freemarker等不适合作为layout,只能用来作为portlet的template. 原因很简单: (1)velocity, freemarker等不支持tag lib. (2) layout template需要调用portlet的render方法。在velocity, freemarker里面直接调用这些复杂java class的各种方法比较别扭,而且得不偿失。 我们可以参照一下我在前面列出的layout jsp,里面调用了大量的java code和tag lib。而用velocity, freemarker来实现这样复杂的layout几乎是不可能的。 和BlueDavy一样,我也有一个开发Portal的计划,用fastm做Portal layout,用fastm做portlet template。 很久以前,我就说过,fastm在Portal layout展现这样的复杂页面逻辑方面,具有任何其他模板技术都无可比拟的优势。由于fastm的逻辑和template完全分离, view层可以达到和Model层一样的OO程度。:-) 不说了,还是先做出来再说。 近两个月来,我下载,研究,并比较了多个商业(免费试用版)和开源Portal的layout实现。结果正如我所料,layout只能基于两种template技术,JSP和xsl(多数Portal采用jsp做layout, 少数Portal用xsl做layout)。这些layout的实现都比较繁琐,而且只能由程序员来做。 这就是为什么几乎所有的Java Portal都把Layout的个数定死了,用户只能从Portal提供的Layout里面选。用户不能很容易地定制Layout – 比如,把Table换成Div等。 为了进一步说明问题,下面我再补充一些Portal的Layout实现。 Sun One Portal – TableColumn.jsp 我们可以看到,Sun One Portal在jsp里面用forEach tag代替了for。 ... <dt:obtainContainer container="$JSPProvider"> <% String columnName = request.getParameter( "columnName" );; %> <% pageContext.setAttribute( "columnName", columnName );; %> <TD WIDTH="<dttable:getColumnWidth column="$columnName"/>%" VALIGN=TOP> <jx:forEach var="channel" items="$channels"> <dtcpc:obtainChannelFromContainer channel="$channel"> <dttable:getIsDetached id="isDetached"/> <jx:declare id="channel" type="java.lang.String"/> <dttable:getProviderCommand id="provider_cmds" scope="request" silentException="true"/> <dt:getTitle id="title" scope="request" silentException="true"/> <jx:if test="$isDetached == false"> <dttable:getHasFrame id="hasFrame" scope="request"/> <dttable:getIsMinimized id="isMinimized" scope="request"/> <dttable:getBorderlessChannel id="borderlessChannel" scope="request"/> <% request.setAttribute("size", "100%");; request.setAttribute("containedChannel", channel);; %> <dtcpc:obtainParentContainer> <dtcpc:containerProviderContext> <%@ include file="leafWrapper.jsp" %> </dtcpc:containerProviderContext> </dtcpc:obtainParentContainer> </jx:if> </dtcpc:obtainChannelFromContainer> <img src="<dt:scontent/>/images/spacer.gif" width="0" height="4" ALT=""><br> </jx:forEach> </TD> </dt:obtainContainer> eXo – PortalRender.java eXo直接把Layout HTML输出写在Java Code里面。for也是写在java code里面。我们可以看到,在eXo里面定制一个新的Layout是多么困难的事情。 ... public void encodeChildren(FacesContext context, UIComponent uiComponent); throws IOException { ExoPortalInfo epcontext = getExoPortalContext(context);; HttpServletResponse response = (HttpServletResponse); context.getExternalContext();.getResponse();; UIPortal uiPortal = (UIPortal); uiComponent ; String encoding = epcontext.getEncoding(); ; response.setLocale(epcontext.getLocale();); ; response.setContentType("text/html;charset=" + encoding); ; ResponseWriter w = context.getResponseWriter();; w.write("\n<!DOCTYPE html\n");; w.write(" PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n");; w.write(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n");; w.write("<html xmlns=\"http://www.w3.org/1999/xhtml\"> \n");; w. write("<head>\n");; w. write("<meta name='keywords' lang='en' content='" + EN_KEYWORD + "' />\n"); ; w. write(uiPortal.getUserCss(););; w. write("<link rel='stylesheet' type='text/css' href='/portal/skin/default-skin.css' />\n");; w. write("</head>\n");; w. write("<body>\n"); ; if(uiPortal.getComponentMode(); == UIPortal.COMPONENT_VIEW_MODE); { renderViewMode(context, uiPortal); ; } else { renderEditMode(context, uiPortal); ; } w. write("</body>\n"); ; w.write("</html>\n"); ; } ... private void renderViewMode(FacesContext context, UIPortal uiPortal); throws IOException { List children = uiPortal.getChildren(); ; for(int i = 0; i < children.size();; i++); { UIBasicComponent uiChild = (UIBasicComponent); children.get(i); ; uiChild.encodeBegin(context);; uiChild.encodeChildren(context);; uiChild.encodeEnd(context);; } ... JPortlet(开源)好像还不支持用户动态添加删除Portlet,必须事先在Layout JSP里面固定写好。 uPortal(开源) – MarkUserLayout.xsl uPortal用xsl做为layout template。uPortal里面包括了SimpleLayout.java等类,为XSL提供XML数据。可见,在uPortal里面添加一个新的Layout选择也不是一件容易的事情。 <!-- add templates --> <xsl:template match="layout|folder" mode="add"> <!-- copy the node and the attributes --> <xsl:copy> <xsl:for-each select="@*"> <xsl:copy/> </xsl:for-each> <xsl:if test="@immutable='false'"> <add_target parentID="{@ID}" nextID="{child::*[self::folder or self::channel][position();=1]/@ID}"/> </xsl:if> <xsl:for-each select="folder|channel"> <xsl:apply-templates mode="add" select="."/> <xsl:if test="@immutable='false'"> <add_target parentID="{../@ID}" nextID="{following-sibling::*[self::folder or self::channel][position();=1]/@ID}"/> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> IBM WebSphere Portal我下载了,由于系统需求太多,没有安装成功,也没有找到Layout实现。但IBM WebSphere Portal是基于JetSpeed的,Layout定义大致和JetSpeed差不多。 Oracle Portal也下载了,也是由于系统需求太多,没有安装成功,也没有找到Layout实现。不知哪位用过Oracle Portal,帮助提供一个Oracle Portal的Layout实现的例子。 我也试图下载Vignette Portal,下载请求正在审核中(Vignette公司需要人工审核下载人的资格)。还不知道能不能通过。 也试图下载Sybase Portal,可能由于网络问题,下载请求一直无法提交。 |
|
返回顶楼 | |
发表时间:2004-09-02
buaawhl,希望能很快看到你的fastm的portal实现!
|
|
返回顶楼 | |
发表时间:2004-09-02
intolong 写道 buaawhl,希望能很快看到你的fastm的portal实现!
多谢支持。:-) |
|
返回顶楼 | |
发表时间:2004-09-02
BlueDavy 写道 1. 需要提供灵活的页面类型机制,可创建各种不同的页面类型,并由用户继承
2. 需要提供灵活的页面布局方式,方便用户频繁变化的需求 3. 同样为了满足用户频繁变化的需求,View层需要有Skin的概念 4. 页面的组织形式需要多种多样,并可轻松转变,如本来是一列按钮形式的布局处需要可换成诸如树状等结构,并且需要与权限结合 这些算是Portal应用的普遍需求了。对于第四点讲讲WLP地实现方式: 1、提供组件树API,所以可以在JSP文件中获得整个组件树的结构从而生成相关的菜单、树型结构等; 2、关于权限,组件树中的对象同样可以被权限系统管理。如果用户不能访问某个Book/Page/Portlet,那么在为该用户生成组件树的时候就不会包含这个组件。View层不用关心任何权限问题。 |
|
返回顶楼 | |
发表时间:2004-09-02
buaawhl 写道 关于WebLogic Portal的“组件树”,主要是通过renderChild tag实现的。
这个说法不对,renderChild 只是在其中少数jsp用到,而且这个tag是把控制权交回给render engine。 WLP的layout可能跟你说的layout可能不是完全相同,在WLP中,book->page->layout。layout只能属于page,一个layout包含多个“格子”,每个“格子”里面可以放多个Portlet。 你在layout.jsp看到的renderChild的实际作用就是通知render engine把当前“格子”里的所有组件 render 出来。绝大部分的组件还是由render engine主动去渲染的。 我本来也有了解当前各个Portal产品的想法,可是迟迟没有动手,惭愧。希望早点看到buaawhl的成果! |
|
返回顶楼 | |