Liferay Portal的相关总结(二)
Portal 与 Portlets三、开始正题
言归正传,要使用Liferay Portal做开发,首先必不可少的要关顾的网站是其官方网站:
http://www.liferay.com/
到了首页,比较醒目的位置是这本书的购买信息:?? ?Liferay in Action 不错,就是这本书,写得不错,我的portal就是看这本书入门的,但是我承认我没花钱,能下载到免费的版本为什么要花钱呢?虽然是这样,请允许我在这里表示一下我对作者的尊敬,真的,谢谢他。这本书写的真的好极了。
????虽然我不是什么大神级的人物,但是我想把我这些日子研究portal的一些成果总结成一篇文章,供大家参考,省得很多刚刚接触portal的童鞋像我刚开始那样迷茫的在互联网海量的数据中穿梭,收获甚微。
????我这个人写东西讲究一个逻辑性,这里我将我写这篇文章的思路解释一下:首先我想用一个小章节介绍一下portal和portlet的特点。如果没有这个打底,我相信后面的内容你会看的很晕。后面的内容准备按照传统的SSH分层的结构,自下向上(也就是数据库,DAO,业务逻辑,前台界面),一层一层展示代码,其间也夹杂着我的一些不成熟的看法,水平有限,如有错误还望各位看官多担待。 四、Portal和Portlet ?? ? ? ? ?portal的特点在于一个portal,就是一个门户页面中,可以嵌入多个portlet,liferay portal能够对每个portlet进行权限控制,对于多个portlet的页面布局进行调整等等。可以看到这个页面由很多小的窗体组成,这些小窗体就是传说中的portlet,这样portal页面与portlet的关系就清楚了,一个或多个portlet组成portal页面。
其实从portlet这个名字我们很容易就想到了跟它名字上很接近的技术——servlet,其实这个portlet与servlet还真是很相像。
?
相同点:
1>???? portlet也同样是java 的web 技术组件
2>???? portlet也是有特定的container在管理
3>???? portlet也可以动态的生成各种内容
4>???? portlet的生命周期由container进行管理
5>???? portlet与客户端的互动也是通过request/response进行的
?
不同点:
1>???? portlet只是整个页面中的一个碎片,有时需要多个portlet协同才能将信息进行完整的展现。
2>???? portlet不直接与URL发生关系
3>???? 客户端必须通过portal系统才能和portlet进行交互
4>???? portlet默认定义portlet的窗口状态,并指出各个状态对应的功能。
5>???? 一个网页中可以存在零个到多个portlet。
首先来看一个最基本的portlet的例子,编程嘛,最简单的例子嘛,还是从Hello World开始吧,别坏了规矩(其实难的我不太会,呵呵~)。
?
首先从整体来看,其实portlet的整个生命周期与servlet不尽相同,但是可以利用servlet的生命周期来理解它,既然和servlet的周期相似就让我们先来回顾一下servlet的周期。servlet的生命周期应该算是学习Java Web 编程的入门课程了,生命周期更应该是熟得不能再熟了,init()进行初始化,service()函数包含该servlet的功能代码段,doGet(),doPost(),destroy()摧毁函数?这样翻译是不是显得太村炮了……
在讲述portlet的生命周期前应该说明的是,每个portlet都有几种状态,这个状态可以理解成,每个状态都对应着一个jsp页面,而通过每个窗体的标题栏上的小扳手(wrench)可以进行状态的切换。然而利用这个进行窗体中页面的切换显得确实很麻烦,所以我不推荐这种办法。portlet默认有三种状态,分别是VIEW(查看态)、EDIT(编辑态)、HELP(帮助态)。当然在高级的portlet编程中可以自定义portlet状态。这些状态也不是所有用户都可见的,管理员是所有状态可见的,其他用户根据所分配权限的不同,看到的内容也不一样。这里已超出我们这片文章的讨论范围。portlet的生命周期也是这样,每个portlet类通过继承GenericPorlet这个基类,这个基类中定义了如下的这些方法:?
public void init(); 或 public void init(PortalConfig pc);?? ? ? ??portlet初始化方法
protected void doView(RenderRequest , RenderRespose );?? ? ? ? ? ?portlet查看态的处理方法
protected void doEdit(RenderRequest , RenderRespose);?? ? ? ? ? ??portlet编辑态的处理方法
protected void doHelp(RenderRequest , RenderRespose);?? ? ? ? ? ??portlet帮助态的处理方法
protected void doDispatcher(RenderRequest , RenderRespose);?? ? ??portlet的分发方法
protected void processAction(RenderRequest , RenderRespose);?? ? ?portlet处理action请求
protected void render(RenderRequest , RenderRespose);?? ? ? ? ? ??portlet处理渲染请求
最后:
public void destroy();?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?portlet终止方法?
?
???????? 下面就列表将servlet生命周期与portlet周期进行比较:
?
?
servlet
portlet
初始化阶段
init();
init();
处理逻辑
service(),doGet(),doPost();
portlet中要处理的请求分为两种,一种是action请求,一种是render请求,然后三种状态分别是View,Edit和Help,分别都有各自的处理函数:(省略参数)
action的请求:??? processAction();
render的请求:??? render();
view状态的请求:? doView();
Edit和Help省略……
释放阶段
destroy();
destroy();
?
说了这么半天理论,来看程序结构,其实跟一般的程序也没什么区别:
?? ?图中可以看到IDE可能是为了清晰,具体为了什么我也不是很清楚,将程序和其他的部分分开,docroot/WEB-INF/src是在上面的,而docroot其他部分在下面。简要分析一下,docroot是默认的根路径,类似于普通ssh程序的WebRoot文件夹,WEB-INF文件夹不用说了,是整个web应用程序的核心文件夹,其中有业务逻辑的源代码src文件夹,不可避免的web.xml文件,整个web应用程序配置描述文件。剩下的这些带有严重liferay色彩的配置文件,从上到下进行解释,liferay-display.xml文件决定这个应用程序被加入到那个分类中去,所谓分类就是在我们向portal中添加portlet时所选择的分类。如下图:
这个portal-display.xml文件就决定这个我们构建的这个portlet在上图中的哪个分类中出现。liferay-plugin-package.properties这个文件定义了一些信息,供配置文件使用。liferay-portlet.xml中定义了这个portlet使用的icon图片文件,css文件,js文件信息以及用户权限配置,规定了用户对于这个portlet的访问权限。最后要介绍我们这些配置文件中最重要的portlet.xml文件,这个配置文件可以说是整个portlet配置的核心。
来看个portlet.xml文件的例子:?
<?xml version="1.0"?>
?
<portlet-app
??? version="2.0"
??? xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??? xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
>?
??? <portlet>
?????? <portlet-name>Demo</portlet-name>
?????? <display-name>Demo</display-name>
?????? <portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
?????? <init-param>
?????????? <name>view-jsp</name>
?????????? <value>/view.jsp</value>
?????? </init-param>
?????? <expiration-cache>0</expiration-cache>
?????? <supports>
?????????? <mime-type>text/html</mime-type>
?????? </supports>
?????? <portlet-info>
?????????? <title>Demo</title>
?????????? <short-title>Demo</short-title>
?????????? <keywords>Demo</keywords>
?????? </portlet-info>
?????? <security-role-ref>
?????????? <role-name>administrator</role-name>
?????? </security-role-ref>
?????? <security-role-ref>
?????????? <role-name>guest</role-name>
?????? </security-role-ref>
?????? <security-role-ref>
?????????? <role-name>power-user</role-name>
?????? </security-role-ref>
?????? <security-role-ref>
?????????? <role-name>user</role-name>
?????? </security-role-ref>
??? </portlet>
</portlet-app>
?
上面是一个我写的简单的portlet的portlet.xml配置文件全文。看着很简单,是因为我的这个portlet很简单。其实高级的portlet编程中,这个portlet中能够配置的信息有很多,比如说像程序中某个控件的默认值,配置验证程序代码所在位置,i18n资源文件位置信息等等。我这篇文档是portal的入门篇,这些内容显然不在我们的讨论范围之内。就上面的这个比较简单的portlet.xml文件为例,我们分析一个这个最简单的portlet.xml中应该配置什么信息?首先是portlet-name和display-name毫无疑问,字面意思,不解释。portlet-class就是我们要用哪个类来处理这个portlet中的业务逻辑,要求全路径(所谓全路径就是要带上包名)。接下来是初始化参数,这个貌似servlet中也有吧,这里不废话了。supports,支持嘛,你懂的。再往下就是portlet的信息嘛。最后是权限配置信息。这个可以说是最为简单的一个portlet的portlet.xml配置信息。
写到这里我突然有种想写一篇中高级的liferay portal编程的文章,也算是预告一下,大家期待一下吧……
下面要讲的是一个很重要的问题,那就是URL的问题,各位看官中不乏Web程序的高手,Java 语言利用其对于String字符串的强大的操纵能力,来个专业点的词汇,就是manipulate the URL string。而这点在portal程序中就会有问题。为什么呢?因为一个portal页面中会集成零个到多个portlet,而每个portlet都是一个单独的jsp页面,这样,如果我只想要其中某个特定的portlet改变其要显示的页面,要怎么实现呢?有人可能提出不是在portlet.xml中配置的了这个portlet的名字嘛?!使用这个啊……我想说这是个办法,但是portal的接口中不是这么干的,它的办法是自己定义一个PortletURL类,利用Response接口下两个子接口,其总体结构图如下:
在处理渲染的函数中利用RenderResponse接口中的createRenderURL这个方法返回一个PorletURL这个类型的返回值,这个就是portal这个系统自动生成的能够定位到这个特定的portlet中特定页面的URL值,伴随整个URL还可以进行传值和取值的操作,并且这个URL还有一个编码过程,这些我在Liferay Portal中高级编程那篇文章中我会介绍,这里就铺垫一下这个portal的特殊的URL机制,钓一下大家胃口。