Portal实现原理

2024-02-18 07:38
文章标签 实现 原理 portal

本文主要是介绍Portal实现原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 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。比如:
<table>
<tr><td>
<jsp:include page=”1.jsp” />
</td></tr>
<tr><td>
<jsp:include page=”3.jsp” />
</td></tr>
<tr><td>
<jsp:include page=”7.jsp” />
</td></tr>
</table>
由于<jsp:include>只能指定固定的jsp文件名,不能动态指定jsp文件名。我们需要把<jsp:include>翻译为Java code – RequestDispatcher.include();
下面我们换成这种写法。

Java代码 复制代码
  1. <table>   
  2. <tr><td>   
  3. <% request.getRequestDispatcher(”1.jsp”).include(request, response); />   
  4. </td></tr>   
  5. <tr><td>   
  6. <% request.getRequestDispatcher(”3.jsp”).include(request, response); />   
  7. </td></tr>   
  8. <tr><td>   
  9. <% request.getRequestDispatcher(”7.jsp”).include(request, response); />   
  10. </td></tr>   
  11. </table>  
<table>
<tr><td>
<% request.getRequestDispatcher(”1.jsp”).include(request, response); />
</td></tr>
<tr><td>
<% request.getRequestDispatcher(”3.jsp”).include(request, response); />
</td></tr>
<tr><td>
<% request.getRequestDispatcher(”7.jsp”).include(request, response); />
</td></tr>
</table>


进一步改进MyPage.jsp。

Java代码 复制代码
  1. <% String[] fileNames = {“1.jsp”, “3.jsp”, “7.jsp”}; %>   
  2. <table>   
  3. <% for(int i = 0; i < fileNames.length; i++) {   
  4.   String fileName = fileName s[i]; %>   
  5. <tr><td>   
  6. <% request.getRequestDispatcher(fileName).include(request, response); />   
  7. </td></tr>   
  8. <% } // end for %>   
  9. </table>  
<% String[] fileNames = {“1.jsp”, “3.jsp”, “7.jsp”}; %>
<table>
<% for(int i = 0; i < fileNames.length; i++) {
String fileName = fileName s[i]; %>
<tr><td>
<% request.getRequestDispatcher(fileName).include(request, response); />
</td></tr>
<% } // end for %>
</table>


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

Java代码 复制代码
  1. <% String[] fileNames = (String[])session.getAttribute(“portlets.config”); %>   
  2. <table>   
  3. <% for(int i = 0; i < fileNames.length; i++) {   
  4.   String fileName = fileNames[i]; %>   
  5. <tr><td>   
  6. <% request.getRequestDispatcher(fileName).include(request, response); />   
  7. </td></tr>   
  8. <% } // end for %>   
  9. </table>  
<% String[] fileNames = (String[])session.getAttribute(“portlets.config”); %>
<table>
<% for(int i = 0; i < fileNames.length; i++) {
String fileName = fileNames[i]; %>
<tr><td>
<% request.getRequestDispatcher(fileName).include(request, response); />
</td></tr>
<% } // end for %>
</table>


2.2 Portlet Interface
下面我们来扩展这个例子。
假设每个Portlet都规定实现一个Portlet接口。

Java代码 复制代码
  1. interface Portlet {   
  2.   void render(request, response);   
  3. };   
  4.   
  5. MyPage.jsp如下:   
  6.   
  7. <% String[] portletClassNames = (String[])session.getAttribute(“portlets.config”); %>   
  8. <table>   
  9. <% for(int i = 0; i < portletClassNames.length; i++) {   
  10.   String className = portletClassNames[i];   
  11.   Portlet portlet = (Portlet)Class.forName(className).newInstance(); %>   
  12. <tr><td>   
  13. <% portlet. render (request, response); />   
  14. </td></tr>   
  15. <% } // end for %>   
  16. </table>   
  17.   
  18. Portlet类的示例代码如下:   
  19. public class Portlet7{   
  20.   public void render(request, response){   
  21.     request.getRequestDispatcher(“7.jsp”).include(request, response);   
  22.   }   
  23. };  
interface Portlet {
void render(request, response);
};
MyPage.jsp如下:
<% String[] portletClassNames = (String[])session.getAttribute(“portlets.config”); %>
<table>
<% for(int i = 0; i < portletClassNames.length; i++) {
String className = portletClassNames[i];
Portlet portlet = (Portlet)Class.forName(className).newInstance(); %>
<tr><td>
<% portlet. render (request, response); />
</td></tr>
<% } // end for %>
</table>
Portlet类的示例代码如下:
public class Portlet7{
public void render(request, response){
request.getRequestDispatcher(“7.jsp”).include(request, response);
}
};


上述代码是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当中。

这篇关于Portal实现原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/720480

相关文章

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核