portlet的编写

gx4air 贡献于2013-03-23

作者 gx4air  创建于2011-12-26 08:06:00   修改者gx4air  修改于2012-03-19 06:55:00字数13197

文档摘要:在需要集成进门户的WEB应用中,web.xml同目录下新建一个portlet.xml,其作用是配置在门户中显示的portlet,如指定对应的java类、初始化参数、不同模式下显示的页面、portlet标题等等。
关键词:

在需要集成进门户的WEB应用中,web.xml同目录下新建一个portlet.xml,其作用是配置在门户中显示的portlet,如指定对应的java类、初始化参数、不同模式下显示的页面、portlet标题等等。 portlet.xml的内容大致如下: FormDemo 表单提交 com.demo.FormDemo text/html VIEW EDIT HELP 表单提交 注意:如果门户的WEB服务器选用Tomcat,web.xml的根节点下加入: com.ibm.websphere.portletcontainer.PortletDeploymentEnabled false 从简单的门户应用来看,可以把portlet当作是servlet,都是java的web组件,都需要容器的管理,都可以产生页面内容,都是通过request/response与客户端交互。但是由于门户的页面是由来自不同WEB应用的多个portlet组成,所以portlet只产生信息片段(div),而不是完整的网页(html),客户端必须通过门户系统才能和portlet互动,即portlet中的URL是一些定义好的request处理,比如action request以及render request,而不是简单的servlet/*.do。下面有5个不同场景的编写portlet的例子帮助理解。 1.portlet提交表单 在portlet中,HTML表单的动作URL可以使用portlet:actionURL标签生成。如:
...
提交该HTML表单将会导致调用portlet的processAction(ActionRequest request, ActionResponse response)方法。像通常一样,可以通过调用request对象的getParameter()方法来获得表单参数。注意:通过提交表单调用动 作,但portlet中却没有processAction()方法,将会导致javax.portlet.PortletException。 package com.demo; import java.io.IOException; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.GenericPortlet; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; public class FormDemo extends GenericPortlet { //尽量不要用实例变量 protected void doEdit(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { // 指定Edit模式下portlet显示的页面 super.doEdit(renderRequest, renderResponse); } protected void doHelp(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { // 指定Help模式下portlet显示的页面 super.doHelp(renderRequest, renderResponse); } protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { // 指定View模式下portlet显示的页面 renderResponse.setContentType("text/html"); PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/WEB-INF/jsp/formDemo.jsp"); dispatcher.include(renderRequest, renderResponse); } public void init() throws PortletException { //可以初始化一些参数 } public void render(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { String move = (renderRequest.getParameter("move")==null) ? "" : renderRequest.getParameter("move"); if( move!=null && "back".equals(move)){ PortletSession session = renderRequest.getPortletSession(); session.setAttribute("newPwd", ""); } super.render(renderRequest, renderResponse); } public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException { //写表单提交后的业务逻辑 String oldPwd = actionRequest.getParameter("oldPwd"); String newPwd = actionRequest.getParameter("newPwd"); PortletSession session = actionRequest.getPortletSession(); session.setAttribute("oldPwd", oldPwd); session.setAttribute("newPwd", newPwd); //执行完上面的业务逻辑之后,portlet将调用render(),进行页面的导航 //processAction()方法设置response对象中的值,要使用ActionResponse对象的setRenderParameter()方法,//而不是setAttribute()方法 } } 编写完portlet类,在portlet.xml配置: FormDemo 表单提交 com.demo.FormDemo text/html VIEW EDIT HELP 表单提交 如果需要为该portlet设置初始化的参数可以在下加入: parameter 100 在portlet类中通过PortletPreferences对象获取: PortletPreferences prefs = request.getPreferences(); String highRangePref = prefs.getValue("parameter", "0"); //如果找不到“parameter”,返回默认值102 portlet类可以通过out方法动态输出信息片段到门户上,但是可以通过portlet+JSP来显示页面信息,这个JSP可以在portlet.xml中指定( ViewPage /WEB-INF/jsp/formDemo.jsp ),也可以在portlet类中的doView()方法中指定。 其中formDemo.jsp的内容如下: <%@ page language="java" import="java.util.*,javax.portlet.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%> 表单提交的Demo <% PortletSession s = renderRequest.getPortletSession(); String newPwd = (String) s.getAttribute("newPwd"); if (newPwd == null || newPwd.length() == 0) { %>
原密码:
新密码:
<% } else { %>
恭喜,密码已成功修改为 <% out.print(newPwd); %>! <% PortletURL backUrl = renderResponse.createRenderURL(); backUrl.setParameter("move", "back"); out.print("返回"); %>
<% } %> 2.portlet分页显示查询结果 portlet中的另一种URL是renderURL,该URL用于操作portlet内容的导航,在portlet类中对应的方法是render()、doView()。 public class QueryDemo extends GenericPortlet { Map datas1 = null; Map datas2 = null; protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { String pageNum = (request.getParameter("pageNum")==null) ? "1" : request.getParameter("pageNum"); int num = Integer.parseInt(pageNum); if(num==1){ request.setAttribute("datas", datas1); request.setAttribute("pageNum", 1); response.setContentType("text/html"); PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/WEB-INF/jsp/queryDemo.jsp"); dispatcher.include(request, response); } if(num==2){ request.setAttribute("datas", datas2); request.setAttribute("pageNum", 2); response.setContentType("text/html"); PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/WEB-INF/jsp/queryDemo.jsp"); dispatcher.include(request, response); } } public void init() throws PortletException { //第一页显示datas1 datas1 = new HashMap(); datas1.put(1, "记录一"); datas1.put(2, "记录二"); datas1.put(3, "记录三"); datas1.put(4, "记录四"); datas1.put(5, "记录五"); //第二页显示datas2 datas2 = new HashMap(); datas2.put(1, "记录六"); datas2.put(2, "记录七"); datas2.put(3, "记录八"); } public void render(RenderRequest request, RenderResponse response) throws PortletException, IOException { //这里做业务处理,通过传参数调用doView() super.render(request, response); } } 在portlet.xml配置的JSP是queryDemo.jsp代码如下: <%@ page language="java" import="java.util.*,javax.portlet.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%> 查询
    <% Map datas = (Map)renderRequest.getAttribute("datas"); for(int i=0; i
  • <% out.print(datas.get(i+1));%>
  • <%} %>
<% //这里没有使用标签效果是一样的。 PortletURL url1 = renderResponse.createRenderURL(); url1.setParameter("pageNum","1"); PortletURL url2 = renderResponse.createRenderURL(); url2.setParameter("pageNum","2"); %>
  上一页   下一页
以上两个例子涉及到两种URL,两种request/response,这里将对此进行简单说明。 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方法。 对于Portlet来说PortletRequest分为ActionRequest和RenderRequest两种,分别是由renderURL和actionURL来触发的。可以这样理解,renderURL是actionURL的一种优化形式。Portlet开发过程中尽可能使用renderURL而避免使用actionURL。actionURL适用于有确实的Action(行为)的情况下。比如说,form表单的递交,Persistent状态的改变,session的操作,preference的修改,这种情况下使用actionURL,而不使用renderURL,renderURL通常用来操作portlet内容的导航。 3.在portlet中调用javascript方法 由于portlet在门户的页面上呈现是一个div,而不是完整的html文件,这就会有很多问题,最明显的就是引用文件或javascript方法时涉及到的命名空间问题。比如某个portlet需要调用名为validate()方法,同一页面中的其他portlet可能也有一个命名为validate()的具有不同逻辑的JavaScript方法。这个问题的解决方法是使用客户端脚本中的名称空间方法和顶层变量。标记将为每个portlet生成一个惟一标识符。 NameSpaceDemo1 JS命名空间1 org.apache.portals.bridges.common.GenericServletPortlet ViewPage /WEB-INF/jsp/nameSpaceDemo1.jsp EditPage /WEB-INF/jsp/nameSpaceDemo1.jsp HelpPage /WEB-INF/jsp/nameSpaceDemo1.jsp text/html VIEW EDIT HELP NameSpaceDemo2 JS命名空间2 org.apache.portals.bridges.common.GenericServletPortlet ViewPage /WEB-INF/jsp/nameSpaceDemo2.jsp EditPage /WEB-INF/jsp/nameSpaceDemo1.jsp HelpPage /WEB-INF/jsp/nameSpaceDemo1.jsp text/html VIEW EDIT HELP 其中在nameSpaceDemo1.jsp中,引入javascript的写法改成: 调用javascript的写法改成: onclick="myFunction(); 在nameSpaceDemo2.jsp中写法nameSpaceDemo1.jsp。 4.portlet中嵌iframe 实验发现portlet中嵌iframe是最方便的portlet内容展示的方式。只需portlet.xml或portlet类中指定JSP,在该JSP中 5.portlet之间的通信 门户可以将不同的portlet连接在一起,portlet之间可以通过事件服务进行通讯,该服务并不是一个可信任的消息服务,很多情况下portlet事件并不能保证能够传到目的地,还有消息死锁的问题,这个需要用程序进行控制,门户没有专门的机制解决。 通过事件进行通信分成两步:事件的声明,事件的接受与处理。 对于一个事件的声明包括三个部分,分别是事件的定义声明、事件的发布载体声明也就是发布该事件的portlet声明、事件接收载体的portlet声明。 其中,事件定义声明是在portlet.xml中使用元素,作为的子元素。 event com.demo.Event 发布事件的portlet声明在portlet.xml中使用元素,作为的子元素。 event 接收事件的portlet声明同上。 事件和载体都声明后,就可以在载体中使用事件。可以在发布事件portlet的processAction()方法中通过调用ActionResponse的setEvent()进行事件的发布,setEvent()方法的输入参数为事件的名称和对应的值。 public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException { String name = (String)request.getParameter("msg"); System.out.println(name); Event e = new Event(); e.setName(name); e.setTime(new Date()); response.setEvent("event", e); } 事件的接收处理在接收事件的portlet的processEvent()方法中进行,通过调用输入参数EventRequest对象的getEvent()方法来获得当前事件,该方法返回一个事件对象,该对象封装了事件的文艺标识和对应的值。 public void processEvent(EventRequest request, EventResponse response) throws PortletException, IOException { javax.portlet.Event event= (javax.portlet.Event)request.getEvent(); com.demo.Event e = (com.demo.Event)event.getValue(); response.setRenderParameter("msg", e.getName()); response.setRenderParameter("date", e.getTime().toString()); } 在对应portet+JSP的JSP中,通过参数传递将事件传递的效果呈现在JSP上。这里就不做赘述。 6.日历 通过以上的一些的实验,成功的将一个开源的日历集成到门户中。 日历

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 3 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档