Portal之Portlet如何与容器交互

Portlet运行在Portlet容器中,由Portlet容器在特定的时间点调用Portlet的方法,那么Portlet应该有哪些方法,这些方法在什么时候被Portlet容器调用呢?本文对此做一个简单的介绍.
Portlet必须实现javax.portlet.Portlet接口,不过在实际的开发中,一般都是实现GenericPortlet,因为GenericPortlet已经提供了一些默认的实现方法.
Portlet和容器的关系如下图所示:Portlet运行在Portlet容器中,负责响应portlet容器的request,对不同的request调用不同的方法,然后生成"html片段",portal server负责将不同的portlet生成的"html片段"组合成一个完整的html页面.(图片来源于Portlet in Action)


和普通http request不同的是,发送到portlet的request的类型不一样,下面是request类型的介绍.
render:当有需要显示内容的时候,容器会向portlet发render request.
action:当有需要portlet完成某个特定业务(比如更新数据库)的时候,容器会向portlet发action request,每一个action request伴随着一个render request.
resource:当有需要resource请求的时候,容器会向portlet发resource request.
event:当有event请求的时候,容器会向portlet发eventrequest.
request 类型有render和action之分的原因是,对于Portal页面上的每一个portlet,其中某一个portlet发生内容发更新后,所有的其他portlet也都需要重新"render",调用响应render request的方法.因为其他portlet用来做显示的数据源有可能被刚刚做更新的那个portlet更新了,但是其他portlet的响应action request的方法是不用被调用的.
下面通过一个实例来说明render,action request由Portlet的那个方法来响应.

  1. public class LifeCyclePortlet extends GenericPortlet {
  2. private String defaultVal;
  3. public void init() {
  4. defaultVal = getPortletConfig().getInitParameter("defaultVal");
  5. System.out.println("******** LifeCyclePortlet init ********");
  6. }
  7. public void init(PortletConfig config) throws PortletException {
  8. System.out.println("******** LifeCyclePortlet init(PortletConfig config) ********");
  9. super.init(config);
  10. }
  11. protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
  12. IOException {
  13. getPortletContext().getRequestDispatcher("/WEB-INF/jsp/preferences.jsp").include(request,
  14. response);
  15. System.out.println("******** LifeCyclePortlet doEdit ********");
  16. }
  17. protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
  18. IOException {
  19. getPortletContext().getRequestDispatcher("/WEB-INF/jsp/help.jsp")
  20. .include(request, response);
  21. System.out.println("******** LifeCyclePortlet doHelp ********");
  22. }
  23. protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
  24. IOException {
  25. System.out.println("LifeCyclePortlet doView " + request.getParameter("reset"));
  26. if ("success".equalsIgnoreCase((String) request.getAttribute("actionStatus"))) {
  27. PortletURL homeUrl = response.createRenderURL();
  28. request.setAttribute("homeUrl", homeUrl);
  29. getPortletContext().getRequestDispatcher("/WEB-INF/jsp/success.jsp").include(request,
  30. response);
  31. return;
  32. }
  33. PortletURL actionUrl = response.createActionURL();
  34. PortletURL resetRenderUrl = response.createRenderURL();
  35. request.setAttribute("actionUrl", actionUrl);
  36. request.setAttribute("resetRenderUrl", resetRenderUrl);
  37. if (!"error".equalsIgnoreCase((String) request.getAttribute("actionStatus"))) {
  38. if ("yes".equalsIgnoreCase(request.getParameter("reset"))) {
  39. defaultVal = "";
  40. } else {
  41. defaultVal = getPortletConfig().getInitParameter("defaultVal");
  42. }
  43. request.setAttribute("someVal", defaultVal);
  44. }
  45. getPortletContext().getRequestDispatcher("/WEB-INF/jsp/inputForm.jsp").include(request,
  46. response);
  47. }
  48. public void processAction(ActionRequest request, ActionResponse response)
  49. throws PortletException, IOException {
  50. System.out.println("******** LifeCyclePortlet processAction ********");
  51. String val = request.getParameter("someVal");
  52. request.setAttribute("val", val);
  53. if (val == null || val.trim().equals("")) {
  54. ResourceBundle bundle = getPortletConfig().getResourceBundle(request.getLocale());
  55. request.setAttribute("errorMsg", bundle.getString("val.errorMsg.missing"));
  56. request.setAttribute("actionStatus", "error");
  57. } else {
  58. request.setAttribute("actionStatus", "success");
  59. }
  60. }
  61. public void render(RenderRequest request, RenderResponse response) throws PortletException,
  62. IOException {
  63. System.out
  64. .println("LifeCyclePortlet render(RenderRequest request, RenderResponse response) "
  65. + request.getParameter("reset"));
  66. super.render(request, response);
  67. }
public class LifeCyclePortlet extends GenericPortlet { 
	private String defaultVal;
	public void init() {
		defaultVal = getPortletConfig().getInitParameter("defaultVal");  
		System.out.println("******** LifeCyclePortlet init ********");
	}
	public void init(PortletConfig config) throws PortletException {
		System.out.println("******** LifeCyclePortlet init(PortletConfig config) ********");
		super.init(config);		
	}
	protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
			IOException {
		getPortletContext().getRequestDispatcher("/WEB-INF/jsp/preferences.jsp").include(request,
				response);
		System.out.println("******** LifeCyclePortlet doEdit ********");
	}
	protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
			IOException {
		getPortletContext().getRequestDispatcher("/WEB-INF/jsp/help.jsp")
				.include(request, response);
		System.out.println("******** LifeCyclePortlet doHelp ********");
	}
	protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
			IOException {
		System.out.println("LifeCyclePortlet doView " + request.getParameter("reset"));
		
		if ("success".equalsIgnoreCase((String) request.getAttribute("actionStatus"))) {
			PortletURL homeUrl = response.createRenderURL();
			request.setAttribute("homeUrl", homeUrl);
			getPortletContext().getRequestDispatcher("/WEB-INF/jsp/success.jsp").include(request,
					response);
			return;
		}
		PortletURL actionUrl = response.createActionURL();
		PortletURL resetRenderUrl = response.createRenderURL();

		request.setAttribute("actionUrl", actionUrl);
		request.setAttribute("resetRenderUrl", resetRenderUrl);

		if (!"error".equalsIgnoreCase((String) request.getAttribute("actionStatus"))) {
			if ("yes".equalsIgnoreCase(request.getParameter("reset"))) {
				defaultVal = "";
			} else {
				defaultVal = getPortletConfig().getInitParameter("defaultVal");
			}
			request.setAttribute("someVal", defaultVal);
		}
		getPortletContext().getRequestDispatcher("/WEB-INF/jsp/inputForm.jsp").include(request,
				response);
	}

	public void processAction(ActionRequest request, ActionResponse response)
			throws PortletException, IOException {
		System.out.println("******** LifeCyclePortlet processAction ********");

		String val = request.getParameter("someVal");
		request.setAttribute("val", val);

		if (val == null || val.trim().equals("")) {
			ResourceBundle bundle = getPortletConfig().getResourceBundle(request.getLocale());
			request.setAttribute("errorMsg", bundle.getString("val.errorMsg.missing"));
			request.setAttribute("actionStatus", "error");
		} else {
			request.setAttribute("actionStatus", "success");
		}
	}
	public void render(RenderRequest request, RenderResponse response) throws PortletException,
			IOException {
		System.out
				.println("LifeCyclePortlet render(RenderRequest request, RenderResponse response) "
						+ request.getParameter("reset"));
		super.render(request, response);
	}
#对上面代码的一个简单解释,以portlet继承了GenericPortlet为例,
当容器初始话的时候,调用init(PortletConfig config)和init()方法.
当有render request到达portlet的时候,render(RenderRequest request, RenderResponse response)方法被调用,根据render的mode不同,会调用doView,doEdit或者doHelp方法.render mode有view,edit,help三种.如下面LifeRay截图,显示A:portlet的"主页面"就是view mode,需要配置preferences(B)为edit mode,需要Help(C)为help mode.
当有action request的时候,调用processAction方法.也可通过Java注解@RenderMode(name = "EDIT"), @ProcessAction(name = "xxxAction")的方式来告诉容器render和action应该有那个方法来响应,这里不做介绍.

如果直接实现Portlet接口的话,只有init(PortletConfig config),render(RenderRequest request, RenderResponse response),processAction(ActionRequest request, ActionResponse response),destroy()四个方法,本例中实现的是GenericPortlet,它对Portlet的方法提供了默认的实现,如render方法会根据render request的mode决定是调用doView,doEdit还是doHelp方法等等.


下面是Portlet用到的显示内容的jsp:

  1. help.jsp:
  2. <table width="200px">
  3. <tr>
  4. <td>
  5. This is the help page
  6. </td>
  7. </tr>
  8. </table>
  9. preference.jsp:
  10. <table width="200px">
  11. <tr>
  12. <td>
  13. This is the preference page for editing options
  14. </td>
  15. </tr>
  16. </table>
  17. inputForm.jsp:
  18. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  19. <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
  20. <%@ page contentType="text/html" isELIgnored="false" %>
  21. <fmt:setBundle basename="content.Language-ext"/>
  22. <form action="<c:out value='${requestScope.actionUrl}'/>" method="POST">
  23. <table width="200px">
  24. <tr>
  25. <td colspan="2">
  26. <font color="#FF0000"><c:out
  27. value="${requestScope.errorMsg}"/></font>
  28. </td>
  29. </tr>
  30. <tr>
  31. <td><font color="#FF0000"><b>*</b></font> <fmt:message key="label.val"/></td>
  32. <td><input type="text" name="someVal" value="${requestScope.someVal}"></input></td>
  33. </tr>
  34. <tr>
  35. <td> </td>
  36. </tr>
  37. <tr align="center">
  38. <td colspan="2">
  39. <input type="submit"/>
  40. <a href="<c:out value='${requestScope.resetRenderUrl}'/>&reset=yes">
  41. <b><fmt:message key="label.reset"/></b>
  42. </a>
  43. </td>
  44. </tr>
  45. </table>
  46. </form>
  47. success.jsp:
  48. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  49. <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
  50. <%@ page contentType="text/html" isELIgnored="false" %>
  51. <fmt:setBundle basename="content.Language-ext"/>
  52. <table>
  53. <tr>
  54. <td colspan="2">action processed successfully</td>
  55. </tr>
  56. <tr>
  57. <td align="right"><b>inputed value is </b></td>
  58. <td><c:out value="${requestScope.val}"/></td>
  59. </tr>
  60. <tr>
  61. <td colspan="2">
  62. <a href="<c:out value='${requestScope.homeUrl}'/>">
  63. <b><fmt:message key="label.home"/></b>
  64. </a>
  65. </td>
  66. </tr>
  67. </table>
help.jsp:
<table width="200px">
  <tr>
  	<td>
  		This is the help page
  	</td>
  </tr>
</table>
preference.jsp:
<table width="200px">
  <tr>
  	<td>
  		This is the preference page for editing options
  	</td>
  </tr>
</table>
inputForm.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page contentType="text/html" isELIgnored="false" %>
<fmt:setBundle basename="content.Language-ext"/>
<form action="<c:out value='${requestScope.actionUrl}'/>" method="POST">
<table width="200px">
  <tr>
  	<td colspan="2">
  		<font color="#FF0000"><c:out 
  		   value="${requestScope.errorMsg}"/></font>
  	</td>
  </tr>
  
  <tr>
  	<td><font color="#FF0000"><b>*</b></font> <fmt:message key="label.val"/></td>
  	<td><input type="text" name="someVal" value="${requestScope.someVal}"></input></td>
  </tr>
  <tr>
  	<td> </td>
  </tr>
  <tr align="center">
    <td colspan="2">
    	<input type="submit"/>
    	 
      <a href="<c:out value='${requestScope.resetRenderUrl}'/>&reset=yes">
        <b><fmt:message key="label.reset"/></b>
      </a>
    </td>
  </tr>
</table>
</form>
success.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page contentType="text/html" isELIgnored="false" %>
<fmt:setBundle basename="content.Language-ext"/>
<table>
	<tr>
		<td colspan="2">action processed successfully</td>
	</tr>
  <tr>
  	<td align="right"><b>inputed value is  </b></td>
  	<td><c:out value="${requestScope.val}"/></td>
  </tr>
    <tr>
  	<td colspan="2">
   		<a href="<c:out value='${requestScope.homeUrl}'/>">
		<b><fmt:message key="label.home"/></b>
		</a>
	</td>
  </tr>
</table>
#help.jsp是在上图中,当点击 "Help"的时候用来显示信息.对应doHelp方法中的Portlet中getPortletContext().getRequestDispatcher("/WEB-INF/jsp/help.jsp")代码.
#preferences.jsp是在上图中,当点击 "Preferences.jsp"的时候用来显示信息.
#inputForm.jsp用来做为Portlet的"主页面",portlet第一次显示的时候会由这个jsp来显示内容.

<form action="<c:out value='${requestScope.actionUrl}'/>" method="POST">的作用指定了form提交时候的action request,这个action url是portlet的java代码PortletURL actionUrl = response.createActionURL();生成的.提交的时候会调用portlet的processAction方法.Portlet URL和普通HTTP URL不同的地方在于,它在普通HTTP URL的基础上加上了一个参数来标识要访问的是哪一个个Portlet,如下面的p_p_id=HelloWorldPortlet_WAR_helloWorld_INSTANCE_MrP9,加上了一个参数用来标识request的类型,如下面的p_p_mode=view,这个URL有Portlet容器解析,就知道了用哪一个portlet的哪一个方法来为一个特定的URL服务了.注意,在不同的Portlet容器中,Portlet URL的参数和值是不同的,下面是LifeRay中的例子.

  1. http://localhost:8080/web/guest/home?p_p_id=HelloWorldPortlet_WAR_h
  2. elloWorld_INSTANCE_MrP9&p_p_lifecycle=1&p_p_state=normal&p_p_mo
  3. de=view&p_p_col_id=column-
  4. 1&p_p_col_count=1&_HelloWorldPortlet_WAR_helloWorld_INSTANCE_MrP9_action=someAction
http://localhost:8080/web/guest/home?p_p_id=HelloWorldPortlet_WAR_h
elloWorld_INSTANCE_MrP9&p_p_lifecycle=1&p_p_state=normal&p_p_mo
de=view&p_p_col_id=column-
1&p_p_col_count=1&_HelloWorldPortlet_WAR_helloWorld_INSTANCE_MrP9_action=someAction

整个项目的structure如下:完整的代码可以从http://download.csdn.net/detail/kkdelta/4084606下载.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值