在一个Portlet中链接到另一个Portlet
这个问题,应该是大部分网站开发人员都希望能解决的问题。典型应用情况:两栏布局,左边是一些链接,右边有一个内容呈现框。当用户点击左边的链接的时候,希望在右边的内容框中显示内容。
在Portal中,一般我们都会把左右做成不同的Portlet。而Portal似乎没有提供直接的方法,能够链接到其他Portlet,通常都是在当前Portlet进行显示。
6.1 Portal的URL格式分析
在一个Portal页面中,Url的格式如何,它是如何将参数传给某一个Portlet的。了解了这些,对解决这个问题应该有所帮助。
这是一个BBS的Url的例子。
http://localhost:8080/c/portal/layout?p_l_id=PRI.15.2&p_p_id=19&p_p_action=0&p_p_state=maximized&p_p_mode=view&p_p_col_id=column-2&p_p_col_pos=0&p_p_col_count=1&_19_struts_action=%2Fmessage_boards%2Fview&_19_categoryId=1
从这个URL分析来看,主要有以下几个参数
p_p_id=19 这个主要是描述当前是在操作哪个Portlet
_19_struts_action=%2Fmessage_boards%2Fview
_19_categoryId=1 这两个是需要传递给Portlet的参数。
如果我们能修改这几个参数,比如,将19换成其他Portlet,应该就可以实现链接到另一个Portlet。
一种做法,是将renderResponse. createRenderURL().toString()进行替换,将其中的portletName换成目标Portlet的portletName。方法应该是可行的,但有点麻烦。尝试找找有没有更好的方法。
6.2 源代码分析
还是从源代码入手,看看Liferay自己是如何处理的。
renderResponse的实现类是com.liferay.portlet.RenderResponseImpl。
public PortletURL createRenderURL() {
return createRenderURL(_portletName);
}
public PortletURL createRenderURL(String portletName) {
…
return portletURL;
}
有希望,我们直接调用createRenderURL(String portletName),将Portlet的名字作为参数传入,应该就可以实现这个目的了。
但是RenderResponse接口并没有createRenderURL(String portletName)这个方法,只能做一下强制转换
PortletURL rowUrl =((com.liferay.portlet.RenderResponseImpl)renderResponse).
createRenderURL(portletName);
rowUrl.setParameter("categoryId", String.valueOf(19));
编写了一点测试代码,对此进行了测试。呵呵,搞定。
6.3 几个实现细节
Portlet有两种类型,是否可实例化。前述的例子,是不可实例化的Portlet,因此只需要使用其Portlet名字19即可。那对于可以实例化的Portlet呢?经过测试发现,需要把其实例化后的名字作为参数传入。
比如一个可实例化的Portlet的名字是56_INSTANCE_95uY。表示其Portlet的名字为56,实例化之后的名字是56_INSTANCE_95uY。把这个名字作为参数传入,即可达到目的。
另一个问题,我们如何将portletName传递给Portlet,让它根据这个参数生成URL?一种做法就是编写Portlet的PortletPreference,在里面保存这个参数名。这样,在不同的页面,我们都可以很方便的实现我们需要的功能。