`

Portal实现原理 转载

阅读更多

出自http://www.iteye.com/topic/7005,转自:http://buaawhl.iteye.com

 

 

    <script type="text/javascript"></script> 关键字:Portal实现原理

    1.Portal用例
    读者可以在下面三个网站上注册自己的用户,体会Portal的功能。
    http://my.msn.com
    http://my.yahoo.com
    http://my.liferay.com

    My MSN的功能最灵活强大,用户可以任意拖放操作栏目(column)和内容版块(content)的位置和个数。
    My Liferay只能选择固定的栏目(column)布局,但可以在本栏目(column)内移动内容版块(content)的位置。
    My Yahoo只能选择固定的栏目(column)布局,而且不能移动内容版块(content)的位置。

    Portal的结构分为三层。
    (1) Page
    (2) Column,或者称为Pane
    (3) Content,或者称为Portlet

    我们来看看Portal的整个操作流程。
    (1) 每个Column的下方都有一个[Add Content]按钮,让用户选择加入自己喜欢的内容。
    从这里,我们知道,Portal系统里面有一个公用的Common Portlet Repository,供用户选用。

    JSR168 Portlet规范里面定义了Portlet Deployment Discriptor。Common Portlet Repository以这个Portlet Deployment Discriptor的格式存放。

    开源项目JetSpeed的XReg文件用来存放Common Portlet Repository的定义。

    (2) 加入Content之后,用户的Page和Column里面就多了这个Content。下次用户登陆的时候,就会看到自己订制的Portal版面。
    从这里,可以看出,Portal系统会纪录用户的个人Portal配置信息 – User Portal Config。

    开源项目JetSpeed的PSML文件用来存放User Portal Config的定义。

    ------- 综上。
    Add Content的整个流程为:
    Common Portlet Repository --> Add Content --> Personal Portal Config

    Display Portal的整个流程为:
    从Personal Portal Config读取用户配置的Portlet ID --> 根据Portlet ID,从Common Portlet Repository查找详细的Portlet定义 --> 根据这个详细的Portlet定义显示这个Portlet。

    2.Portal实现
    我们考虑如何用Java来实现Portal。

    2.1 Dynamic Include
    首先,我们采用最简单的思路,我们用100个JSP文件(1.jsp, 2.jsp, 3.jsp, … 100.jsp等),代表100个Portlet。
    用户页面MyPage.jsp包含用户选定的多个Portlet。
    现在,假设用户选取的Portlet为1.jsp, 3.jsp, 7.jsp等3个Portlet,那么我们如何在MyPage.jsp中显示这些Portlet?最直观的做法是,用jsp:include。比如:





    <jsp:include page="&amp;rdquo;1.jsp”">

    <jsp:include page="&amp;rdquo;3.jsp”">

    <jsp:include page="&amp;rdquo;7.jsp”">

    由于<jsp:include>只能指定固定的jsp文件名,不能动态指定jsp文件名。我们需要把<jsp:include>翻译为Java code – RequestDispatcher.include();
    下面我们换成这种写法。
    [code="java"]





    <% request.getRequestDispatcher(”1.jsp”).include(request, response); />

    <% request.getRequestDispatcher(”3.jsp”).include(request, response); />

    <% request.getRequestDispatcher(”7.jsp”).include(request, response); />

    [/code]
    进一步改进MyPage.jsp。
    [code="java"]
    <% String[] fileNames = {“1.jsp”, “3.jsp”, “7.jsp”}; %>

    <% for(int i = 0; i < fileNames.length; i++) {
    String fileName = fileName s[i]; %>

    <% } // end for %>

    <% request.getRequestDispatcher(fileName).include(request, response); />

    [/code]
    其中的fileNames的内容可以各种各样,只要RequestDispatcher能够处理。
    比如Velocity,fileNames = {“1.vm”, “3.vm”, “7.vm”};
    比如URL,fileNames = {“/portlet1.do”, “/portlet3.do”, “/portlet4.do”};
    我们可以看到,如果我们从用户配置中读取fileNames的内容,这就是一个简单的Portal实现。
    [code="java"]
    <% String[] fileNames = (String[])session.getAttribute(“portlets.config”); %>

    <% for(int i = 0; i < fileNames.length; i++) {
    String fileName = fileNames[i]; %>

    <% } // end for %>

    <% request.getRequestDispatcher(fileName).include(request, response); />

    [/code]
    2.2 Portlet Interface
    下面我们来扩展这个例子。
    假设每个Portlet都规定实现一个Portlet接口。
    [code="java"]
    interface Portlet {
    void render(request, response);
    };

    MyPage.jsp如下:

    <% String[] portletClassNames = (String[])session.getAttribute(“portlets.config”); %>

    <% for(int i = 0; i < portletClassNames.length; i++) {
    String className = portletClassNames[i];
    Portlet portlet = (Portlet)Class.forName(className).newInstance(); %>

    <% } // end for %>

    <% portlet. render (request, response); />


    Portlet类的示例代码如下:
    public class Portlet7{
    public void render(request, response){
    request.getRequestDispatcher(“7.jsp”).include(request, response);
    }
    };
    [/code]
    上述代码是Portal显示Portlet的核心流程的一个简化版本。
    JSR168 Portlet规范里面定义了真正的Portlet接口定义。

    2.3 Portlet Action
    Portlet的操作包括,最大化/最小化/恢复/关闭/编辑/帮助/上下移动,等等。
    这些操作都有对应的Action类。
    开源项目JetSpeed的module/actions/controls目录下面包含Maximize, Minimize, Close等Action类。
    开源项目Liferay的portal/action目录下面包含Maximize, Minimize, Close等Action类。

    Portal的操作不仅包括上述Portlet的操作,而且包括其它更高级别的操作。
    比如,Add/Move Page, Add/Move Column, 换Layout, 换Skin,之类。

    2.4 Portlet Cache
    我们操作Portlet的时候,往往只操作某个特定的Portlet,或者只是变化Portlet的位置。这时候,页面中大多数的Porlet的内容是不变的,只有一小块Portlet变化。
    我们需要把Portlet的内容缓存起来。Portlet接口有一个render(request, response)方法,我们可以订制定制response类,截获portlet的输出,保存到Portal系统的内容Cache当中。
    比如,前面提到liferay开源项目,其StringServletResponse类把Portlet的输出保存到一个String当中。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics