posts - 12, comments - 19, trackbacks - 0, articles - 23
  语源科技BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Portlet应用开发 (JSR168)(四)

Posted on 2006-08-10 20:50 毛里求斯的化石 阅读(1433) 评论(0)  编辑  收藏 所属分类: portal相关

By Terry.li

SpiritSeekerS@sqatester.com

 

 

本文使用本系列中 Part1 搭建的开发环境 , 如果没有搭建好开发环境 , 请参考 Portlet 应用开发 Part1 进行开发环境的搭建 . 在 Part1 中我们已经介绍了 Portlet 的 GenericPortlet 类 . 从形式上来看 , Portlet 与 Servlet 非常相似 , 但是从 request 和 response 对象的具体特点及功能来说 , 又有所不同 . 本部分主要描述了 Portlet 的 Request 和 Response 对象 的特点及其与 Servlet 的 Request 和 Response 对象 的不同点 .

 

l          Portlet 的 Request 对象

Portlet 中的 Request 与 Servlet 的 Request 一样接受 Client 端发送的 Request, 但是与 Servlet 不同 , Portlet 的 Request 分为 Action Request 及 Render Request 两种类型 , 因此 Portlet 接口中定义了两种方法用来处理不同的 Request. 分别是 processAction(ActionRequest request,ActionResponse response) 和 render(RenderRequest request,RenderResponse response), 分别用以处理 Action Request 和 Render Request. 某种意义上来讲 ,render 方法类似 Servlet 中的 service 方法 ,doView,doEdit,doHelp 方法又类似 doGet,doPost 方法 , 如下图 :

 

 

1.             RenderRequest 和 ActionRequest 有什么不同呢 ?
对于 Portlet 来说 PortletRequest 分为 ActionRequest 和 RenderRequest 两种 , 分别是由 renderURL 和 actionURL 来触发的 . 可以这样理解 , renderURL 是 actionURL 的一种优化形式 .Portlet 开发过程中尽可能使用 renderURL 而避免使用 actionURL. actionURL 适用于有确实的 Action( 行为 ) 的情况下 . 比如说 , form 表单的递交 . Persistent 状态的改变, session 的操作, preference 的修改 , 这种情况下使用 actionURL, 而不使用 renderURL, renderURL 通常用来操作 portlet 内容的导航 .

 

以下是两个例子:

使用 actionURL:
<%

PortletURL pu=renderResponse.createActionURL();

pu.setParameter("ACTION","LOGIN");

…

%>

<form name="usrfrm" method="post" action="<%=pu.toString()%>">

 

注 : form 表单递交时,使用 HTTP post 方法,而不用 get 方法.因为某些 Portal/Portlet Container 的实现将内部状态编码到 URL 的 Query 字符串中.

 

 

使用 renderURL:

<%

PortletURL pu=renderResponse.createRenderURL();

pu.setParameter("PAGE",Number);

…

%>

<a href=”<%=pu%>”> 下一页 </a>

 

2.     renderURL 和 actionURL 的处理方式有什么不同?

当客户端 request 是由 一个 renderURL 触发 时, Portlet/Portlet Container 会调用 Portal 页面中所有 Portlet 的 render 方法. 如下 :

 

renderURL

/       |           \

                                                              render     render  render  

 

 

而 当客户端 request 一个 actionURL 触发时 , Portlet/Portlet Container 会先调用目标 Portlet 的 processAction() 方法, 当 processAction 方法处理完毕后 , 再分别调用 Portal 页面中所有 Portlet 的 render 方法.如下 :

                          actionURL

                                 | 

                                processAction

                                /        |         \

                        render     render     render

 

由于以上原因,所以使用 renderURL 要比使用 actionURL 的 performance 来的好.

 

3.     RenderRequest 和 ActionRequest 的 parameter 参数作用范围有什么不同?

当客户端 request 一个 actionURL 触发时,比如一个 form 表单的提交,所有的 Parameter 的 get 操作必须在 processAction 方法中进行 . 例如:

 

JSP 的 form 表单页面 :

<%

PortletURL pu=renderResponse.createActionURL();

pu.setParameter("ACTION","LOGIN");

…

%>

<form name="usrfrm" method="post" action="<%=pu.toString()%>">

…

 

Portlet 的处理:

public void processAction (ActionRequest req,ActionResponse res){

   String str=req.getParameter(“ACTION”);

   //response.setRenderParameter("ACTION",action);

}

 

public void doView(ActionRequest req,ActionResponse res){

   String str=req.getParameter(“ACTION”);

}

 

如上 processAction 方法中, getParamter 方法将能成功得到表单中的参数 ACTION 所对应的值 , 因为我们知道,当目标 portlet 的 processAction 方法运行完后, Portlet Container 将调用 Portal 页面中所有 Portlet 的 render 方法.但是实际上 doView 方法中使用 getParameter 不会得到任何值.但是如果把 processAction 方法中注释了的一行 uncomment 的话,你就可以在 doView 方法中的得到参数 ACTION 对应的值. 这说明 action request 的参数, render 方法中不可以直接取到.必须使用了 setRenderParameter 方法,再次传递一次.

 

 

l          A case study

在这部分中 , 我们来做一个简单的 Portlet, 实现一个简单的 Form submit 功能 . 以下是代码片段 : ( 完整代码请参考文章末尾 )

 

JSP( view_portletrequest.jsp.jsp ):

 

… …

<!-- Use PortletURL Object//-->

<%

PortletURL pu1=renderResponse.createActionURL();

pu1.setParameter( "ACTION" , "Use PortletURL Object" );

pu1.setPortletMode(PortletMode.VIEW);

%>

 

< table width =100% border =0>

< TR >< TD >1. Use PortletURL object to get an ActionURL and set current portlet mode to view</ TD ></ TR >

< tr >< td >

< form name ="usrfrm" method ="post" action =" <%= pu1.toString() %> ">

  < input type =submit name =bt1 value ="GetActionByJava">

</ form >

< tr >< td >

</ table >

       … …

        

       注 : 处理完 form 后将会将 PortletMode 设定为 VIEW .

 

以上代码使用了 actionURL 因为是 form 表单的递交 . 详细请参考 Portlet 的 Request 对象 部分 . 或者也可以使用 Tag. 它同样也可以生成一个 Portlet 的 URL, 如下 :

 

… …

<!-- Use Portlet Tag //-->

<portlet:actionURL windowState="maximized" portletMode="edit" var ="pu2">

<portlet: param name =" ACTION " value ="Use Portlet Tag"/>

</portlet:actionURL>

 

< BR >

< table width =100% border =0>

< TR >< TD >2. Use Portlet Tag to get a ActionURL and and set current portlet mode to edit</ TD ></ TR >

< tr >< td >

< form name ="usrfrm" method ="post" action =" <%= pu2 %> ">

       < input type =submit name =bt2 value ="GetActionByTag">

</ form >

< tr >< td >

</ table >

… …

 

注 : 它在处理完 form 后将会将 PortletMode 设定为 EDIT , 并且 Window state 会为最大化 .

 

Portlet ( PortletRequestExample . java ):

 

… …

    public void processAction(ActionRequest request, ActionResponse response)

              throws PortletException, IOException

       {

              String action=request.getParameter( "ACTION" );

              System.out.println( "ACTION" + action);

              if (action== null ){

                     action= "" ;

              }

             

              response.setRenderParameter( "ACTION" ,action);

}

… …

 

 

       JSP( view_portletrequest.jsp )

 

       … …

       <%

String getaction= "" ;

if ( request .getParameter( "ACTION" )!= null ){

  getaction= request .getParameter( "ACTION" );

}

%>

 

< B > ACTION : <%= getaction %> </ B >

       … …

   

 

JSP( edit_portletrequest.jsp.jsp )

 

… …

<%

String getaction= "" ;

if ( request .getParameter( "ACTION" )!= null ){

  getaction= request .getParameter( "ACTION" );

}

%>

< B > ACTION : <%= getaction %> </ B >

… …

 

将以上源代码编译后 , 再通过 Eclipse 生成 / 更新 Portlet 的 web.xml 后 ,  将所有配置及相关文件部署后 , 启动 Tomcat.

 

 

 

在 Browser 中加载如下页面 : Http://localhost:8080/pluto/portal , 可以看到如下的页面 ( 图 :4-1)

 

图 :4-1

 

 

单击 PortletRequest Example Page 后可以看到如下 Portlet 页面 ( 图 4-2)

 

图 :4-2

 

 

 

单击 GetActionByJava 后 , 得到如下 ( 图 :4-3):

 

    图 :4-3

 

单击 GetActionByTag 后 , 将跳转到 edit mode, 如下 ( 图 :4-4):

 

         图 :4-4

 

l          Portlet 的 Re sponse 对象
与 Request 对象类似, Response 对象也有两种:分别是 ActionResponse 和 RenderResponse, 分别封装了对应 ActionRequest 和 RenderRequest 对象返回的所有信息。例如,重定向, windows state,portlet mode 等的信息。其中他们的父类, PortletResponse 拥有 setProperty 和 addProperty 方法,用以传递提供商指定的信息给 portal/portlet container

1
。 ActionResponse 和 RenderResponse 有什么不同?

ActionResonse
可以用来处理以下相关功能:
1)
重定向
sendRedirect
方法用来进行帮助 portal/portlet-container 进行头信息,及其内容的设定 , 并且将 URL 重定向到用户指定的页面。
2)
改变 windows state, portlet mode ,我们在以前章节中介绍了 window state 和 portlet mode 概念 .
3)
传递 Parameter 参数到 RenderRequest 中去,如上面 request 部分中用到的例子。


RenderResponse
用来提供如下功能 ( 和 Servlet 中的 Response 更相似 ) :
1)
设置 ContentType
2)
得到 Output Stream and Writer 对象,用来产生页面内容

3) Buffering
4)
设定 Portlet 的 Title , 但必须先于 portlet 的输出递交前来调用,否则将会被忽略。 (注:目前的 pluto 没有实现,如果调用不会修改 title )

l          A example


… …

 public void doView(RenderRequest request, RenderResponse response)

       throws PortletException, IOException

{

response.setContentType("text/html");

PrintWriter pw=response.getWriter();

pw.print(“Hello, Portlet”);

      … …

 

     

·          源 代码及 Portlet 相关配置文件

 

A. Portlet ( PortletRequestExample .java )

 

package portlets.portletrequest;

 

/**

  * @author terry

  *

  * To change the template for this generated type comment go to

  * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

  */

import javax.portlet.*;

import java.io.IOException;

 

public class PortletRequestExample extends GenericPortlet{

 

  public void doView(RenderRequest request, RenderResponse response)

       throws PortletException, IOException

  {

       response.setContentType( "text/html" );

 

       String jspName = getPortletConfig().getInitParameter( "view" );

 

       PortletRequestDispatcher rd =

         getPortletContext().getRequestDispatcher(jspName);

 

       rd.include(request, response);

  }

 

  public void doEdit(RenderRequest request, RenderResponse response)

       throws PortletException, IOException

  {

       response.setContentType( "text/html" );

 

       String jspName = getPortletConfig().getInitParameter( "edit" );

 

       PortletRequestDispatcher rd =

         getPortletContext().getRequestDispatcher(jspName);

 

       rd.include(request, response);

  }

 

       public void processAction(ActionRequest request, ActionResponse response)

              throws PortletException, IOException

       {

              String action=request.getParameter( "ACTION" );

              System.out.println( "ACTION" + action);

              if (action== null ){

                     action= "" ;

              }

             

              response.setRenderParameter( "ACTION" ,action);

       }

}
      

B. JSP (view_portletrequest.jsp )

      

<%@ page session = "false" %>

<%@ page import = "javax.portlet.*" %>

<%@ page import = "java.util.*" %>

<%@ taglib uri= '/WEB-INF/tld/portlet.tld' prefix= 'portlet' %>

<portlet:defineObjects/>

< BR >

< h3 >Request Example</ h3 >

 

<!-- Use PortletURL Object//-->

<%

PortletURL pu1=renderResponse.createActionURL();

pu1.setParameter( "ACTION" , "Use PortletURL Object" );

pu1.setPortletMode(PortletMode.VIEW);

%>

 

< table width =100% border =0>

< TR >< TD >1. Use PortletURL object to get an ActionURL and set current portlet mode to view</ TD ></ TR >

< tr >< td >

< form name ="usrfrm" method ="post" action =" <%= pu1.toString() %> ">

       < input type =submit name =bt1 value ="GetActionByJava">

</ form >

< tr >< td >

</ table >

 

<!-- Use Portlet Tag //-->

<portlet:actionURL windowState="maximized" portletMode="edit" var ="pu2">

<portlet: param name =" ACTION " value ="Use Portlet Tag"/>

</portlet:actionURL>

 

< BR >

< table width =100% border =0>

< TR >< TD >2. Use Portlet Tag to get a ActionURL and and set current portlet mode to edit</ TD ></ TR >

< tr >< td >

< form name ="usrfrm" method ="post" action =" <%= pu2 %> ">

       < input type =submit name =bt2 value ="GetActionByTag">

</ form >

< tr >< td >

</ table >

 

<%

String getaction= "" ;

if ( request .getParameter( "ACTION" )!= null ){

       getaction= request .getParameter( "ACTION" );

}

%>

 

ACTION : < B > <%= getaction %> </ B >

 

< BR >< BR >

Current Portlet Mode: < B >< big > <%= renderRequest.getPortletMode() %> </ big ></ font ></ B >< br >

 

 

C. JSP (edit_portletrequest.jsp )

 

<%@ page session = "false" %>

<%@ page import = "javax.portlet.*" %>

<%@ page import = "java.util.*" %>

<%@ taglib uri= '/WEB-INF/tld/portlet.tld' prefix= 'portlet' %>

<portlet:defineObjects/>

< BR >

< h3 >Request Example</ h3 >

 

 

<%

String getaction= "" ;

if ( request .getParameter( "ACTION" )!= null ){

       getaction= request .getParameter( "ACTION" );

}

%>

 

ACTION : < B > <%= getaction %> </ B >

 

< BR >< BR >

Current Portlet Mode: < big >< B > <%= renderRequest.getPortletMode() %> </ font ></ big ></ B >< br >

     

D. Portlet.xml

 

    … …

    <!-- PortletRequest Example -->

       <portlet>

              <description>PortletRequest Example</description>

              <portlet-name>PortletRequestExample</portlet-name>

              <display-name>PortletRequest Example</display-name>

              <portlet-class>portlets.portletrequest.PortletRequestExample</portlet-class>

             

              <init-param>

                     <name>view</name>

                     <value>/fragments/portletrequest/view_portletrequest.jsp</value>

              </init-param>

              <init-param>

                     <name>edit</name>

                     <value>/fragments/portletrequest/edit_portletrequest.jsp</value>

              </init-param>

 

              <expiration-cache>-1</expiration-cache>

              <supports>

                     <mime-type>text/html</mime-type>

                     <portlet-mode>VIEW</portlet-mode>

                     <portlet-mode>EDIT</portlet-mode>

              </supports>

              <supported-locale>en</supported-locale>

              <portlet-info>

                     <title>PortletRequest Example</title>

                     <short-title>PortletRequest</short-title>

                     <keywords>PortletRequest</keywords>

              </portlet-info>

       </portlet>

       … …

 

E. portletentityregistry.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<portlet-entity-registry>

  <application id="10">

  <definition-id>portlets</definition-id>

  … …

        <portlet id="30">

                 <definition-id>portlets.PortletRequestExample</definition-id>

        </portlet>

  … …

  </application> 

       </portlet-entity-registry>

 

F. pageregistry.xml

 

<?xml version="1.0"?>

<portal>

 

    <fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">

    </fragment>

 

… …

 

<!-- PortletRequest Example Page -->

    <fragment name="portletrequestpage" type="page">

        <navigation>

            <title>PortletRequest Example Page</title>

            <description>PortletConfig Example Page</description>

        </navigation>

         <fragment name="row1" type="row">

            <fragment name="col1" type="column">

                <fragment name="p1" type="portlet">

                    <property name="portlet" value="10.30"/>

                </fragment>

            </fragment>

         </fragment>

</fragment>

 

… …

 

</portal>

 

 

注 : web.xml 文件可以从 portlet.xml 通过 Eclipse 的 Plugin 直接生成 , 所以没有列出配置文件 , 请参考本系列中的 Part1.

 

      资源 :

·   Pluto
http://jakarta.apache.org/pluto

·   Pluto Mail List
http://news.gmane.org/gmane.comp.jakarta.pluto.user

·   WSRP Spec1.0
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp

·   Apache 的 WSRP 实现
http://ws.apache.org/wsrp4j/

·   Apache’s Portal, JetSpeed:
http://jakarta.apache.org/jetspeed/site/index.html

·   JSR 168:
http://www.jcp.org/en/jsr/detail?id=168

·   "Portlet 规范介绍 " By Stefan Hepper 和 Stephan Hesmer