CSDN博客

img snowdot23

复杂portlet开发

发表于2004/7/12 11:03:00  1479人阅读

portlet 从天气服务中动态检索指定的邮政编码所代表的地区的天气情况。此外,消息也不再是硬编码的,而是委托给 JSP 去处理。

图 5. 增强的 Weather Portlet 代码样本

package com.ibm.wps.samples.weather; import java.io.*; import vendor.service.weather.*; import org.apache.jetspeed.portlet.*; import org.apache.jetspeed.portlets.*; import org.apache.jetspeed.portlet.service.*; /** * WeatherPortlet.java ?A more extensive example to display weather. */ public class WeatherPortlet extends PortletAdapter { protected static final String jsp = "/WEB-INF/weather/html/DisplayWeather.jsp"; public void init(PortletConfig portletConfig) throws UnavailableException { super.init(portletConfig); } public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { // Create a Weather Bean. WeatherBean weatherBean = new WeatherBean(); // Get the portlet session. PortletSession session = request.getPortletSession(); // Get the portlet configuration. PortletConfig config = getPortletConfig(); // Get the portlet context. PortletContext context = config.getContext(); // Get portal user object. User user = session.getUser(); // Get the user's full name or null if not available. weatherBean.setFullName(user.getFullName()); // Get the weather service for determining the temperature. WeatherService weatherService = (WeatherService)context.getService(WeatherService.class); // Get the current temperature for the specified zip code. weatherBean.setTemperature( weatherService.getTemperature( Integer.parseInt(config.getInitParameter("ZipCode")))); // Put the bean in the request. request.setAttribute("weatherBean", weatherBean); // Invoke the JSP to do the actual rendering for the portlet view. context.include(jsp, request, response); } }

我们来仔细研究一下这个示例来考察其中的一些重要组件。第一件要注意的事情是 WeatherPortlet 类不再继承 AbstractPortlet 类,而是继承 PortletAdapter 类。PortletAdapter 类是中心 portlet 抽象,即 portlet 接口的一个实现。它为下列 portlet 方法提供缺省的空实现:init、login、service、logout 和 destroy。

接下来要注意的是该类不再直接覆盖 service 方法。而是覆盖与特定的 portlet 模式相关联的方法。Portlet 有四种模式的操作:

  • Portlet.Mode.VIEW
  • Portlet.Mode.EDIT
  • Portlet.Mode.HELP
  • Portlet.Mode.CONFIGURE

从这些模式的名称中就可以看出它们的操作。对于每种模式,PortletAdapter 类都提供一个缺省的空实现方法。在图 5 中,portlet 只支持 VIEW 模式,所以只有一个相应的 doView 方法被覆盖。service 方法的缺省实现确定 portlet 模式并调用适当的模式方法,下图 6 中的代码片段指出了这一点:

图 6. 确定 portlet 模式

... public void service(PortletRequest request, PortletResponse response) throws PortletException, IOException { // Get the mode of the portlet. Portlet.Mode mode = request.getMode(); if (mode == Portlet.Mode.VIEW) doView(request, response); else if (mode == Portlet.Mode.EDIT) doEdit(request, response); else if (mode == Portlet.Mode.HELP) doHelp(request, response); else if (mode == Portlet.Mode.CONFIGURE) doConfigure(request, response); } ... 

我们来研究一下当调用 portlet 去处理它的 VIEW 模式时会发生什么情况。

发生的第一件事是将创建一个 WeatherBean 实例(图 7),这个实例将包含处理显示所需的所有相关数据,在本例中是用户名和预先配置的邮政编码所代表的地区的天气情况。如代码所示,用户名是从 user 对象检索出来的。为确定温度,首先从 PortletConfig 对象检索邮政编码(这里,我们简化的假设是这个 portlet 是由管理员为某个邮政编码所代表地区的全部用户配置的)。第二件事是获取对 PortletService 的引用(具体到这个示例就是引用 WeatherService 对象)。为限制这个示例的复杂性,我们将假设已经向门户服务器注册了天气服务,并且 portlet 可以利用这个服务获取特定的邮政编码所代表的地区的当前天气情况。一旦获得了这两条信息,就将它们存储在 WeatherBean 中。

图 7. WeatherBean 代码样本

package com.ibm.wps.samples.weather; /** * WeatherBean.java ?A bean used to pass data to the JSP display. */ public class WeatherBean { /** The user's full name. */ private String fullName = ""; /** The current temperature. */ private int degrees = 0; public void setFullName(String name) { fullName = name; } public String getFullName() { return fullName; } public void setTemperature(int degrees) { this.degrees = degrees; } public int getTemperature() { return degrees; } }

这个 bean 被从 PortletAdapter 类传递到 JSP,这个 JSP 将最终处理显示。这是通过 PortletRequest 对象的 setAttribute 方法完成的。然后 JSP 将使用 useBean 标记建立对 WeatherBean 的引用,并将用户的全名值和当前的温度嵌入到 HTML 输出标志(markup)中。

图 8. DisplayWeather 代码样本

<!-----------------------------------------------------------------------------> <!-- --> <!-- DisplayWeather.jsp - A JSP used to render the data for the weather --> <!-- portlet. --> <!-- --> <!-----------------------------------------------------------------------------> <%@ page contentType="text/html" errorPage="" %> <jsp:useBean id="weatherBean" class="com.ibm.wps.samples.weather.WeatherBean" scope="request"/> <p> Hi <%= weatherBean.getFullName() == null ? "" : weatherBean.getFullName() %>! <br> The current temperature in your area is <%= weatherBean.getTemperature() %>.

这个 portlet 的输出(图 9)看起来与我们前面的示例相似。

图 9. 增强的 Weather Portlet

增强的 Weather Portlet

目前为止,我们只研究了严格按浏览器(如 IE 和 Netscape,它们实现整个 HTML 规范)处理其显示的 portlet。但如果您想将 portlet 扩展到这些胖客户机之外,并使内容可以由受限的设备(比如袖珍 PC 机、手持设备或智能电话)使用时,又会怎样?在下面的几部分中,我们将研究 IBM WebSphere Portal 提供的额外 API,这些 API 可以帮助为这些设备进行开发工作。我们还将研究更高级的问题,这些问题目前在这些 API 中尚未解决,我们甚至还将演示增加发布的方法的方法。

这个示例中并没有讨论关于一些更高级 portlet API 论题的细节问题,比如窗口状态、事件处理、实例数据等,相关信息请参考 WebSphere Portal InfoCenter(请参阅参考资料)。

介绍普及的编程

面向对象设计的其中一个设计模式是模型-视图-控制器(Model-View-Controller),也称 MVC。MVC 简单的令人惊讶,但却是一个非常有用的模式,它要求开发者按照下面三个基本组件来构思应用程序:

  • 模型(model)是主要的组件,它维护应用程序呈现出的状态和数据模型。
  • 控制器(controller)是模型及其视图之间的桥梁。它是一个组件,用户可以使用它来更改底层数据模型。
  • 视图(view)是数据模型面向用户的图形化表示。

这种设计的强大之处在于它提供了:

  • 通明性?这种设计的逻辑组件是明确分开的。
  • 模块性?应用程序的各种组件可以按您的需要调进调出,使调试工作更加容易。
  • 多个视图?在多个实现中视图是可伸缩的,可以用来体现同一个数据模型。
  • 可伸缩的设计?随着应用程序的增长,各种组件也能够增长,同时不影响底层的应用程序逻辑。

图 10. 模型-视图-控制器(MVC)设计模式

模型

普及的 portlet 编程技术

既然我们了解了进行应用程序开发的模块化方法的背景知识,那么我们就把它应用到普及的编程中吧。我们可以对天气(Weather)示例中的组件做如下分析:

模型: 核心天气应用程序,比如通过访问用户的全名或天气服务来检索当前的温度。
控制器: 供应 bean,这些 bean 把 portlet 代码和 JSP 之间的数据连接起来。
视图: 处理 portlet 内容的图形化显示的 DisplayWeather JSP。

现在很容易就可以看到不管处理的实际显示是什么样子,模型都维持不变。在各个视图之间控制器基本上是保持不变的,但可能需要按照期望的视图对数据执行一些特定的定制工作。视图组件具有处理数据使它们最适合目标显示器的灵活性。例如,智能电话以 WML(无线标记语言(Wireless Markup Language))格式显示内容。于是,对于我们的天气示例,我们可以为每个期望的设备定义一个单独的视图 JSP:为浏览器定义一个 HTML JSP,为智能电话定义一个 WML JSP。看一下图 11 中的样本 portlet,它使用这个设计模式和 WebSphere Portal 的普及 API。

图 11. 为每个设备定义单独的视图

package com.ibm.wps.samples.weather; import java.io.*; import com.ibm.wps.portlets.*; import vendor.service.weather.*; import org.apache.jetspeed.portlet.*; import org.apache.jetspeed.portlets.*; import org.apache.jetspeed.portlet.service.*; /** * WeatherBaseController.java * Base controller class containing common controller functionality. */ public class WeatherBaseController extends AbstractPortletController { /** The View for HTML devices (e.g. Internet Explorer, Netscape). */ protected String jspHTML = "/WEB-INF/weather/html/"; /** The View for WML devices (e.g. SmartPhones). */ protected String jspWML = "/WEB-INF/weather/wml/"; public void init(PortletConfig config) throws UnavailableException { super.init(config); // Load the HTML View from the configuration jspHTML += config.getInitParameter("view.HTML"); // Load the WML View from the configuration. jspWML += config.getInitParameter("view.WML"); } protected void createBean(PortletRequest request, PortletResponse response) { // Get the portlet configuration object. PortletConfig config = getPortletConfig(); // Create a Weather Bean. WeatherBean weatherBean = new WeatherBean(); // Set the user's full name or null if not available. weatherBean.setFullName( request.getPortletSession().getUser().getFullName()); // Get the weather service for determining the temperature. WeatherService weatherService = (WeatherService)config.getContext().getService(WeatherService.class); // Get the current temperature for the specified zip code. weatherBean.setTemperature( weatherService.getTemperature( Integer.parseInt(config.getInitParameter("ZipCode")))); // Insert bean into the request for the JSP to use. request.setAttribute("weatherBean", weatherBean); } }
package com.ibm.wps.samples.weather; import java.io.*; import com.ibm.wps.portlets.*; import org.apache.jetspeed.portlet.*; /** * WeatherHTMLController.java * Controller for calling the HTML View. */ public class WeatherHTMLController extends WeatherBaseController { public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { createBean(request, response); getPortletConfig().getContext().include(jspHTML, request, response); } }
package com.ibm.wps.samples.weather; import java.io.*; import com.ibm.wps.portlets.*; import org.apache.jetspeed.portlet.*; /** * WeatherWMLController.java * Controller for calling the WML View. */ public class WeatherWMLController extends WeatherBaseController { public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { createBean(request, response); getPortletConfig().getContext().include(jspWML, request, response); } }

这个示例显示了一个基本的控制器,它包含 HTML 和 WML 视图的公共功能。首先,在 init 方法中,加载来自 portlet 配置的 HTML 和 WML 视图 JSP 的名称。然后,提供一个名为 createBean 的方法,这个方法创建一个 WeatherBean 实例并向它植入模型数据。最后,createBean 方法把 bean 插入到请求中,使它能被视图 JSP 使用。

接下来的两个类(图 12)提供每种视图类型的控制器。第一个是 HTML 控制器,第二个是 WML 控制器。这两个控制器类都继承控制器基类来继承后者提供的通用功能。为简单起见,除调用的视图不同之外,这两个控制器之间并没有太多不同之处。但您可以考虑根据用户所采取的操作提供为每种设备类型定制的特别功能。例如,一个胖客户机控制器可以提供对图标的拖放控制,而瘦客户机控制器却不会。

为使这些控制器能工作,您需要向 portlet web.xml 文件注册它们,方法是添加下列配置标志。(web.xmlportlet.xml 文件的详细信息不在本示例内。要了解更多信息,请参阅参考资料部分的 WebSphere Portal InfoCenter 文档。)

图 12. HTML 与 WML 控制器

... <servlet-name>WeatherPortlet</servlet-name> <servlet-class>com.ibm.wps.portlets.MVCPortlet</servlet-class> <init-param> <param-name>controller.html</param-name> <param-value>com.ibm.wps.samples.weather.WeatherHTMLController</param-value> </init-param> <init-param> <param-name>controller.wml</param-name> <param-value>com.ibm.wps.samples.weather.WeatherWMLController</param-value> </init-param> <init-param> <param-name>view.HTML</param-name> <param-value>DisplayWeatherHTML.jsp</param-value> </init-param> <init-param> <param-name>view.WML</param-name> <param-value>DisplayWeatherWML.jsp</param-value> </init-param> <init-param> <param-name>ZipCode</param-name> <param-value>27709</param-value> </init-param> ... 

现在,我们需要提供两个视图 JSP,一个用于 HTML,另一个用于 WML(图 13)。由于 HTML 视图是用于胖客户机的,我们将在其中显示用户名,但在 WML 视图中将省略用户名,因为这个是更受限制的客户机。

图 13. HTML 与 WML JSP

<!-----------------------------------------------------------------------------> <!-- DisplayWeatherHTML.jsp - A JSP view for rendering HTML. --> <!-----------------------------------------------------------------------------> <%@ page contentType="text/html" errorPage="" %> <jsp:useBean id="weatherBean" class="com.ibm.wps.samples.weather.WeatherBean" scope="request"/> <p> Hi <%= weatherBean.getFullName() == null ? "" : weatherBean.getFullName() %>! <br> The current temperature in your area is <%= weatherBean.getTemperature() %>.
<!-----------------------------------------------------------------------------> <!-- DisplayWeatherWML.jsp - A JSP view for rendering WML. --> <!-----------------------------------------------------------------------------> <%@ page contentType="text/wml" errorPage="" %> <jsp:useBean id="weatherBean" class="com.ibm.wps.samples.weather.WeatherBean" scope="request"/> <p align="left"> Current temperature is <%= weatherBean.getTemperature() %>. </p>

图 14 和图 15 分别显示了如何在浏览器和智能电话上处理这些 portlet。

图 14. 使用 HTML JSP 的 Weather Portlet

使用 HTML JSP 的 Weather Portlet

图 15. 使用 WML JSP 的 Weather Portlet

0 0

相关博文

我的热门文章

img
取 消
img