集成 Adobe Flex 和 IBM WebSphere Portal

本文通过实例来介绍如何将 Adobe Flex 集成到 IBM WebSphere Portal 中。您可以使用 Adobe Flex 作为客户端解决方案来向用户呈现 portlet 界面,不仅克服了 HTML 的限制,而且显著改善用户的门户体验。

Shade El-Hadik, 高级顾问 IT 专家, WSO2 Inc

Shade El-Hadik 是 IBM WebSphere Portal、IBM Lotus Web Content Management 和电子商务实践的高级顾问 IT 专家。Shade 从事 J2EE 和 Web 开发已超过 5 年,并且为 WebSphere 产品家族开发了许多门户应用程序。



2010 年 2 月 08 日

编辑注:您很精通这个主题吗?希望分享您的经验吗?请马上加入到 IBM Lotus 软件 wiki 项目。

简介

本文解释了如何集成 Adobe Flex 和 IBM WebSphere Portal portlet。文章首先以使用 Adobe Flex Builder 构建一个 Flex 项目开始,然后显示如何构建 Web 服务。最后,将所有组件集成到一个 portlet 页面中。本文也介绍了如何显示和更新一个简单的雇员列表。第二个例子的思路和第一个例子相同,如何使用后端 servlet 通过 WebSphere Portal 框架让 Flex 应用程序与 JSON 对象通信。文章还显示了这两个例子的所有必要代码,并逐行解释它们。它演示了借助 Flex HTTP 服务、SOA Web 服务和 JSON 系列化,使用 JSR-168 portlet 将富 Internet 应用程序(RIA)与 WebSphere Portal 集成在一起是一个可行的、无缝的过程。

富 Internet 应用程序(RIA)为用户提供丰富的、有吸引力的体验,并且能够提高生产力。借助遍布全球的 Internet,可以跨浏览器和桌面部署 RIA。Adobe Flex 是一个免费的开放源码框架,用于构建可以一致地部署到所有主流浏览器、桌面和操作系统的高度可交互、表达性很强的 Web 应用程序。它提供一种现代的、基于标准的语言和编程模型,并且支持常见的设计模式。MXML 是基于 XML 的声明式语言,用于描述用户界面(UI)布局和行为;ActionScript3 是一种强大的面向对象编程语言,用于创建客户端逻辑。Flex 为不同的浏览器提供一致的观感。

WebSphere Portal 是一个将不同来源的内容聚合到一个集成 UI 中的 Web 应用程序。Portal 还通过内置的安全基础设施提供个性化特性和单点登录;它们还可以与各种独立供应商的解决方案集成。JSON (JavaScript™ Object Notation) 是一种轻量级的数据交换格式。JSON 为服务器和客户端应用程序之间的数据交换引入一种新的格式,从而减少了 HTTP 流量。


先决条件

您应该对以下技术有深入的理解:

  • Java™ Runtime Environment 1.5.0 或更新版本
  • Web 服务器(比如 IBM WebSphere Application Server V6.0 或 Apache Tomcat V6.0)
  • WebSphere Portal V6.0
  • IBM Rational® Software Architect V7.0 或更新版本
  • Adobe Flex Builder(V2.0 或更新版本))
  • MySQL server V5.0 或更新版本

在 WebSphere Portal 中运行 SOA Web 服务 Flex 应用程序

这个例子展示如何运行 Adobe Flex 应用程序。Adobe Flex 应用程序调用一个名为 EmployeesDB 的 Web 服务,该服务通过 Java Database Connectivity (JDBC) 连接到数据库。这个 Web 服务有两个方法:

  • 第一个方法是 getEmployees(),它返回一个雇员的名称及其标识符的列表。为了保持简单,这个列表使用 Xstream API 进行序列化。
  • 第二个方法是 updateEmployee(),它接受一个被序列化为 XML 文件的 ActionScript 对象,名为 employee。

这个例子演示了如何构建 Flex 应用程序和 portlet 应用程序,并演示集成 Adobe Flex 和 WebSphere Portal 有多么容易。

遵循以下步骤构建一个 portlet 应用程序:

  1. 打开 Rational Software Architect。
  2. 选择 File - New - Project。
  3. 在显示的 New Project 窗口中,展开 Portal 文件夹并选择 Portlet Project。单击 Next。
  4. 在显示的 New Portlet Project 窗口中,在 Project name 字段输入 FlexWebService。在这个步骤,您创建了一个扩展在 Java Portlet Specification Version 1.0 (JSR 168) 中定义的 GenericPortlet 类的基础 portlet。完成以下步骤:

    • 在 Target Runtime 字段中选择 WebSphere Portal v6.0。
    • 在 EAR Membership 部分接受默认设置。
    • 在 Portlet API 字段中选择 JSR 168 Portlet。
    • 在 Create a portlet 部分接受默认设置。
    • 选择 Show advance settings 选项。
  5. 单击 Next。

    图 1. 定义 portlet 项目
    定义 portlet 项目
  6. 在显示的 Project Facets 窗口中,以下设置是默认的选项:

    • Dynamic Web Module
    • Java
    • JSR 168 Portlets
    • JSR 168 Portlets on WebSphere Portal

    单击 Next 接受默认选项,如图 2 所示。

    图 2. Project Facets 窗口
    Project Facets 窗口
  7. 在显示的 Portlet Settings 窗口中,选择了以下默认设置:

    • 对于内容类型和模式,text/html 是内容类型,view 是模式。
    • 选择了 Generate a custom portlet class 选项,默认的 Package prefix 被设置为 com.ibm.flexwebservice,默认的 Class prefix 被设置为 FlexWebServicePortlet。
    • 在 locale-specific information 部分,默认选择 en。

    通过单击 Next 接受默认值。如图 3 所示。

    图 3. Portlet Settings 窗口
    Portlet Settings 窗口
  8. 在显示的 Action and Preferences 窗口中,取消选择所有选项(见图 4)并单击 Finish。

    图 4. Action and Preferences 窗口
    Action and Preferences 窗口
  9. 打开 FlexWebService 项目,右键单击 WebContent 文件夹。创建一个名为 movies 的新文件夹。FlexWebService portlet 的文件夹结构类似于图 5。

    图 5. 添加新的 movies 文件夹之后的文件夹结构
    添加新的 movies 文件夹之后的文件夹结构
  10. 修改包含在 com.ibm.flexwebservice 包中的 portlet 类以让它调用 doView() 方法中的 FlexWebServicePortletView.jsp,如清单 1 所示。
清单 1. FlexWebServicePortlet.java
Line:1    package com.ibm.flexwebservice;
Line:2    
Line:3    import java.io.*;
Line:4    import java.util.*;
Line:5    import javax.portlet.*;
Line:6    
Line:7    /**
Line:8     * A sample portlet based on GenericPortlet
Line:9     */
Line:10   public class FlexWebServicePortlet extends GenericPortlet {
Line:11   
Line:12   	public static final String JSP_FOLDER    = "/_FlexWebService/jsp/";    
                // JSP folder name
Line:13   
Line:14   	public static final String VIEW_JSP      = "FlexWebServicePortletView";  
                //JSP file name to be rendered on the view mode
Line:15   
Line:16   	/**
Line:17   	 * @see javax.portlet.Portlet#init()
Line:18   	 */
Line:19   	public void init() throws PortletException{
Line:20   		super.init();
Line:21   	}
Line:22   
Line:23   	/**
Line:24   	 * Serve up the <code>view</code> mode.
Line:25   	 * 
Line:26   	 * @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, 
                    javax.portlet.RenderResponse)
Line:27   	 */
Line:28   	public void doView(RenderRequest request, RenderResponse response) 
                throws PortletException, IOException {
Line:29   		// Set the MIME type for the render response
Line:30   		response.setContentType(request.getResponseContentType());
Line:31   
Line:32   
Line:33   		// Invoke the JSP to render
Line:34   		PortletRequestDispatcher rd = getPortletContext().
                    getRequestDispatcher (getJspFilePath(request, VIEW_JSP));
Line:35   		rd.include(request,response);
Line:36   	}
Line:37   
Line:38   	/**
Line:39   	 * Returns JSP file path.
Line:40   	 * 
Line:41   	 * @param request Render request
Line:42   	 * @param jspFile JSP file name
Line:43   	 * @return JSP file path
Line:44   	 */
Line:45   	private static String getJspFilePath(RenderRequest request, 
                String jspFile) {
Line:46   		String markup = request.getProperty("wps.markup");
Line:47   		if( markup == null )
Line:48   			markup = getMarkup(request.getResponseContentType());
Line:49   		return JSP_FOLDER + markup + "/" + jspFile + "." 
                   + getJspExtension(markup);
Line:50   	}
Line:51   
Line:52   	/**
Line:53   	 * Convert MIME type to markup name.
Line:54   	 * 
Line:55   	 * @param contentType MIME type
Line:56   	 * @return Markup name
Line:57   	 */
Line:58   	private static String getMarkup(String contentType) {
Line:59   		if( "text/vnd.wap.wml".equals(contentType) )
Line:60   			return "wml";
Line:61           else
Line:62               return "html";
Line:63   	}
Line:64   
Line:65   	/**
Line:66   	 * Returns the file extension for the JSP file
Line:67   	 * 
Line:68   	 * @param markupName Markup name
Line:69   	 * @return JSP extension
Line:70   	 */
Line:71   	private static String getJspExtension(String markupName) {
Line:72   		return "jsp";
Line:73   	}
Line:74   
Line:75   }
  1. 在 _FlexWebService/jsp/html 文件夹中可以找到 FlexWebServicePortletView.jsp。在 div 标记内部定义 OBJECT 和 EMBED 标记,如清单 2 的 17 至 34 行所示。
清单 2. FlexWebServicePortletView.jsp
Line:1    <%@page session="true" contentType="text/html" 
             pageEncoding="ISO-8859-1" import="javax.portlet.*" %>
Line:2    <%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
Line:3    <portlet:defineObjects/>
Line:4    
Line:5    <style type="text/css">
Line:6    		#fxJavaScript { width: 90%; height: 500px; }
Line:7    		#html_controls {width: 15em; margin-top: 1em; padding: 1em;
Line:8    				color: white; border: solid 1px white;
Line:9    				font-family: Arial
Line:10   		}
Line:11   		body<#html_controls {	width: 13em;}
Line:12   		body {background-color: #869CA7;}
Line:13   </style>
Line:14   
Line:15   <div>
Line:16   
Line:17   		<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
Line:18   		  id="SampleUpdate" width="100%" height="500px"
Line:19   		 codebase="http://fpdownload.macromedia.com/get/flashplayer/
                      current/swflash.cab">
Line:20   			<param name="movie" value="<%=renderResponse.encodeURL
                        (renderRequest.getContextPath()+"/movies/
                        WebServiceFlex.swf")%>" />
Line:21   			<param name="quality" value="high" />
Line:22   			<param name="bgcolor" value="#869ca7" />
Line:23   			<param name="allowScriptAccess" value="sameDomain" />
Line:24   	<embed src="<%=renderResponse.encodeURL
                (renderRequest.getContextPath()+"/movies/WebServiceFlex.swf")%>"
Line:25   			quality="high" bgcolor="#869ca7"
Line:26   			width="100%" height="500px" name="SampleUpdate" 
                        align="middle"
Line:27   			play="true"
Line:28   			loop="false"
Line:29   			quality="high"
Line:30   			allowScriptAccess="sameDomain"
Line:31   			type="application/x-shockwave-flash"
Line:32   			pluginspage="http://www.adobe.com/go/getflashplayer">
Line:33   			</embed>
Line:34   		 </object>
Line:35   
Line:36   </div>

通过以下步骤在 Adobe Flex Builder 内部创建一个新的 Flex 项目:

  1. 在显示的新 Flex Project 窗口中,在 Project name 字段中输入 WebServiceFlex,然后单击 Finish。

    现在,项目文件夹的结构如图 6 所示。

    图 6. Flex 项目的结构
    Flex 项目的结构
  2. 根据清单 3 中的代码修改 WebServiceFlex.mxml 文件。下面的清单 3 逐行解释了这些代码。
清单 3. WebServiceFlex.mxml
Line:1    <?xml version="1.0" encoding="utf-8"?>
Line:2    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
             xmlns="*" layout="horizontal"
Line:3    creationComplete="onCreationComplete()">
Line:4    	
Line:5    
Line:6    	<mx:Script>
Line:7         <![CDATA[
Line:8            
Line:9    	   import mx.controls.Alert; 
Line:10   	   import mx.rpc.xml.SimpleXMLEncoder;
Line:11         import mx.utils.ObjectUtil;
Line:12         import mx.rpc.events.ResultEvent;
Line:13         import mx.rpc.events.FaultEvent;
Line:14   
Line:15   
Line:16    [Bindable]
Line:17   	private var myXML:XML;
Line:18   			
Line:19     private function onCreationComplete():void {
Line:20   		webService.getEmployees().send;
Line:21   	}
Line:22   				
Line:23   		private function callWS(evt:ResultEvent):void {
Line:24   		  var retVal:Object = evt.result;
Line:25   		  var newMessage:String = 
                      retVal as String;				
Line:26   		  myXML = new XML(newMessage);
Line:27   		  myGrid.dataProvider = myXML.Employee;	
Line:28   	}
Line:29   				
Line:30   				
Line:31   	     private function choosenItem(selectedItem:Object):void {
Line:32   	        formPanel.visible = false;
Line:33   			employeeObj.name      = selectedItem.name;
Line:34   			employeeObj.identifer = selectedItem.identifer;
Line:35   			formPanel.visible = true;
Line:36   			formPanel.setStyle("showEffect","fadeIn");
Line:37   			  }
Line:38   	          
Line:39   	      private function update(employeeObj:Object):void {
Line:40   	          var xml:XML = objectToXML(employeeObj);
Line:41   	          webService.updateEmployee(xml.toString());
Line:42   	          webService.getEmployees().send;
Line:43   	         }
Line:44   	          
Line:45   	      private function objectToXML(obj:Object):XML {
Line:46   	          var qName:QName = new QName("Employee");
Line:47   	          var xmlDocument:XMLDocument = new XMLDocument();
Line:48   	          var simpleXMLEncoder:SimpleXMLEncoder = 
                          new SimpleXMLEncoder(xmlDocument);
Line:49   	          var xmlNode:XMLNode = 
                          simpleXMLEncoder.encodeValue(obj, qName, xmlDocument);
Line:50   	          var xml:XML = new XML(xmlDocument.toString());
Line:51   	          // trace(xml.toXMLString());
Line:52   	          return xml;
Line:53   	        }
Line:54   
Line:55           ]]>
Line:56         </mx:Script>
Line:57   	
Line:58      <mx:Fade id="fadeIn" duration="1000" alphaFrom="0.0" alphaTo="1.0"/>
Line:59   	
Line:60      <mx:WebService id="webService"
Line:61              wsdl="http://localhost:8080/EmployeeWS/wsdl/EmployeesDB.wsdl">
Line:62           <mx:operation name="getEmployees" result="callWS(event);" />
Line:63       </mx:WebService>
Line:64   
Line:65   	<mx:Panel title="Employees" width="100%" height="100%">
Line:66   	<mx:DataGrid id="myGrid" labelField="{choosenItem(myGrid.selectedItem)}"  
                width="100%" height="50%"> 
Line:67   		<mx:columns>
Line:68   		<mx:DataGridColumn headerText="name" dataField="name" />
Line:69   		<mx:DataGridColumn headerText="identifer" dataField="identifer" />
Line:70       	</mx:columns>
Line:71   	</mx:DataGrid>
Line:72   	<mx:PieChart id="profitPie" dataProvider="{myXML.Employee}"  
                showDataTips="true" width="100%" height="50%">
Line:73         <mx:series>
Line:74           	<mx:PieSeries field="identifer" nameField="name" 
                        labelPosition="callout" />
Line:75         	  </mx:series>
Line:76       	</mx:PieChart>
Line:77     		
Line:78   	</mx:Panel>
Line:79   
Line:80   
Line:81   	<Employee id="employeeObj"
Line:82   		name="{employeeName.text}"
Line:83   		identifer="{identifer.text}"/>
Line:84   		
Line:85   		<mx:Panel id="formPanel" title="Form" width="100%" 
                    height="10%" visible="false" showEffect="{fadeIn}">	
Line:86   		<mx:Form width="100%"> 
Line:87   		  <mx:FormItem label="Name">
Line:88   			<mx:TextInput id="employeeName" 
                        text="{employeeObj.name}"/>
Line:89   			</mx:FormItem>
Line:90   			<mx:FormItem label="Identifer">
Line:91   				<mx:TextInput id="identifer" editable="false" 
                            text="{employeeObj.identifer}"/>
Line:92   			</mx:FormItem>
Line:93   		</mx:Form>
Line:94   
Line:95   		<mx:ControlBar>
Line:96   		<mx:Button buttonDown="true" label="Update" 
                    click="update(employeeObj);onCreationComplete();"/>
Line:97   		</mx:ControlBar>
Line:98   	</mx:Panel>
Line:99   	
Line:100  
Line:101  </mx:Application>

该代码的第 2 和第 3 行显示应用程序标记 mx:Application。Flex 定义了一个默认的应用程序容器,您可以通过它为应用程序添加内容,而不需显式地定义其他容器。您可以将布局指定为水平对齐,这意味着 movie 中包含的两个面板是相邻的。此外,您还可以对 CreationComplete 事件调用 onCreationComplete() 函数。CreationComplete 是在整个组件(及其子组件)完全创建之后、在组件的生命周期的末尾触发的。

第 19 至 21 行显示 onCreationComplete 函数的声明。在这个函数中,您可以通过调用 getEmployees() 方法来调用 webservice 函数。

在调用了 getEmployees() 函数之后,使用返回的结果调用 callWS() 函数,如第 23 至 28 行所示。在这个函数中,您可以构建一个 XML 对象并将其绑定到数据表格的 dataProvider 属性。

第 31 至 37 行显示了数据表格的 label 函数。chosenItem 函数传递在数据表格中选择的整个行。您可以将该行的值绑定到 employee 对象。反过来,employee 对象将绑定到表单字段。第 36 行显示了如何为表单添加渐退效果。

第 39 至 43 行显示 update 函数,在单击 Update 按钮时调用该函数。我们在这个函数中调用 Web 服务函数 updateEmployee()。

第 60 至 63 行显示一个调用 Web 服务的 WebService 组件。这个 WebService 组件调用两个 Web 服务操作 getEmployees() 和 updateEmployee()。

第 65 至 78 行显示数据表格和一个嵌入到标题为 “Employees” 的面板中的饼图。数据表格有两个列,即 name 和 identifier。您可以使用 PieSeries 图表系列和 PieChart 控件为该图表定义数据。将标识符指定为一个字段属性,让图表知道使用哪个值来创建大小适合的楔形饼图。

第 81 至 84 行显示初始化 employee 对象。这个类仅有两个字段,即 name 和 identifier。

第 85 至 93 行显示用于更新雇员数据的表单。

注意,showEffect="{fadeIn}" 字段中的 fadeIn 效果显示应用程序的工作流。可以在第 58 行中找到渐退效果的声明和属性。您可以将 visible 属性指定为 false,这样表单在开始时是不可见的,例如 visible="false"。您可以将 editable 属性指定为 false,让字段标识符变得不可编辑,例如 editable="false"。

第 95 至 97 显示了 Update 按钮。在出现单击事件时,它将调用 update 函数并传递可以绑定到表单字段 name 和 identifier 的 employee 对象。

  1. 接下来,右键单击 src 文件夹并添加一个名为 Employee.as 的新 ActionScript 类。

    根据清单 4 修改 Employee.as。

清单 4. Employee.as
Line:1    package
Line:2    {
Line:3    	[Bindable] 
Line:4    
Line:5    	public class Employee
Line:6    	{
Line:7    		public function Employee()
Line:8    		{
Line:9    		}
Line:10   
Line:11   		public var name:String;
Line:12   
Line:13   		public var identifer:String;
Line:14   
Line:15   
Line:16   	}
Line:17   }
  1. 单击 Export Release Build 按钮 Export Release Build 按钮 添加 bin-release 文件夹。在该文件夹中可以找到 WebServiceFlex.swf 短片,这是 portlet 应用程序需要使用的文件。
  2. 将 WebServiceFlex.swf 文件移动到先前创建的 movies 文件夹中的 portlet 项目。

您可以看到 EmployeesDB.wsdl 代码,如清单 5 所示。

清单 5. EmployeesDB.wsdl
Line:1    <?xml version="1.0" encoding="UTF-8"?>
Line:2    <wsdl:definitions targetNamespace="http://flex.ibm.com" 
             xmlns:apachesoap="http://xml.apache.org/xml-soap" 
             xmlns:impl="http://flex.ibm.com" xmlns:intf="http://flex.ibm.com" 
             xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap=
             "http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd=
             "http://www.w3.org/2001/XMLSchema">
Line:3    <!--WSDL created by Apache Axis version: 1.4
Line:4    Built on Apr 22, 2006 (06:55:48 PDT)-->
Line:5     <wsdl:types>
Line:6      <schema elementFormDefault="qualified" targetNamespace=
               "http://flex.ibm.com" xmlns="http://www.w3.org/2001/XMLSchema">
Line:7       <element name="main">
Line:8        <complexType>
Line:9         <sequence>
Line:10         <element maxOccurs="unbounded" name="arg" type="xsd:string"/>
Line:11        </sequence>
Line:12       </complexType>
Line:13      </element>
Line:14      <element name="mainResponse">
Line:15       <complexType/>
Line:16      </element>
Line:17      <element name="getEmployees">
Line:18       <complexType/>
Line:19      </element>
Line:20      <element name="getEmployeesResponse">
Line:21       <complexType>
Line:22        <sequence>
Line:23         <element name="getEmployeesReturn" type="xsd:string"/>
Line:24        </sequence>
Line:25       </complexType>
Line:26      </element>
Line:27      <element name="updateEmployee">
Line:28       <complexType>
Line:29        <sequence>
Line:30         <element name="SubShadeXMLString" type="xsd:string"/>
Line:31        </sequence>
Line:32       </complexType>
Line:33      </element>
Line:34      <element name="updateEmployeeResponse">
Line:35       <complexType>
Line:36        <sequence>
Line:37         <element name="updateEmployeeReturn" type="xsd:string"/>
Line:38        </sequence>
Line:39       </complexType>
Line:40      </element>
Line:41      <element name="sendEmail">
Line:42       <complexType>
Line:43        <sequence>
Line:44         <element name="sendTO" type="xsd:string"/>
Line:45         <element name="subject" type="xsd:string"/>
Line:46         <element name="message" type="xsd:string"/>
Line:47        </sequence>
Line:48       </complexType>
Line:49      </element>
Line:50      <element name="sendEmailResponse">
Line:51       <complexType>
Line:52        <sequence>
Line:53         <element name="sendEmailReturn" type="xsd:string"/>
Line:54        </sequence>
Line:55       </complexType>
Line:56      </element>
Line:57     </schema>
Line:58    </wsdl:types>
Line:59   
Line:60      <wsdl:message name="sendEmailResponse">
Line:61   
Line:62         <wsdl:part element="impl:sendEmailResponse" name="parameters"/>
Line:63   
Line:64      </wsdl:message>
Line:65   
Line:66      <wsdl:message name="getEmployeesRequest">
Line:67   
Line:68         <wsdl:part element="impl:getEmployees" name="parameters"/>
Line:69   
Line:70      </wsdl:message>
Line:71   
Line:72      <wsdl:message name="getEmployeesResponse">
Line:73   
Line:74         <wsdl:part element="impl:getEmployeesResponse" name="parameters"/>
Line:75   
Line:76      </wsdl:message>
Line:77   
Line:78      <wsdl:message name="mainRequest">
Line:79   
Line:80         <wsdl:part element="impl:main" name="parameters"/>
Line:81   
Line:82      </wsdl:message>
Line:83   
Line:84      <wsdl:message name="mainResponse">
Line:85   
Line:86         <wsdl:part element="impl:mainResponse" name="parameters"/>
Line:87   
Line:88      </wsdl:message>
Line:89   
Line:90      <wsdl:message name="sendEmailRequest">
Line:91   
Line:92         <wsdl:part element="impl:sendEmail" name="parameters"/>
Line:93   
Line:94      </wsdl:message>
Line:95   
Line:96      <wsdl:message name="updateEmployeeResponse">
Line:97   
Line:98        <wsdl:part element="impl:updateEmployeeResponse" name="parameters"/>
Line:99   
Line:100     </wsdl:message>
Line:101  
Line:102     <wsdl:message name="updateEmployeeRequest">
Line:103  
Line:104        <wsdl:part element="impl:updateEmployee" name="parameters"/>
Line:105  
Line:106     </wsdl:message>
Line:107  
Line:108     <wsdl:portType name="EmployeesDB">
Line:109  
Line:110        <wsdl:operation name="main">
Line:111  
Line:112           <wsdl:input message="impl:mainRequest" name="mainRequest"/>
Line:113  
Line:114           <wsdl:output message="impl:mainResponse" name="mainResponse"/>
Line:115  
Line:116        </wsdl:operation>
Line:117  
Line:118        <wsdl:operation name="getEmployees">
Line:119  
Line:120           <wsdl:input message="impl:getEmployeesRequest" 
                       name="getEmployeesRequest"/>
Line:121  
Line:122           <wsdl:output message="impl:getEmployeesResponse" 
                       name="getEmployeesResponse"/>
Line:123  
Line:124        </wsdl:operation>
Line:125  
Line:126        <wsdl:operation name="updateEmployee">
Line:127  
Line:128           <wsdl:input message="impl:updateEmployeeRequest" 
                       name="updateEmployeeRequest"/>
Line:129  
Line:130           <wsdl:output message="impl:updateEmployeeResponse" 
                       name="updateEmployeeResponse"/>
Line:131  
Line:132        </wsdl:operation>
Line:133  
Line:134        <wsdl:operation name="sendEmail">
Line:135  
Line:136           <wsdl:input message="impl:sendEmailRequest" 
                       name="sendEmailRequest"/>
Line:137  
Line:138           <wsdl:output message="impl:sendEmailResponse" 
                       name="sendEmailResponse"/>
Line:139  
Line:140        </wsdl:operation>
Line:141  
Line:142     </wsdl:portType>
Line:143  
Line:144     <wsdl:binding name="EmployeesDBSoapBinding" type="impl:EmployeesDB">
Line:145  
Line:146        <wsdlsoap:binding style="document" 
                    transport="http://schemas.xmlsoap.org/soap/http"/>
Line:147  
Line:148        <wsdl:operation name="main">
Line:149  
Line:150           <wsdlsoap:operation soapAction=""/>
Line:151  
Line:152           <wsdl:input name="mainRequest">
Line:153  
Line:154              <wsdlsoap:body use="literal"/>
Line:155  
Line:156           </wsdl:input>
Line:157  
Line:158           <wsdl:output name="mainResponse">
Line:159  
Line:160              <wsdlsoap:body use="literal"/>
Line:161  
Line:162           </wsdl:output>
Line:163  
Line:164        </wsdl:operation>
Line:165  
Line:166        <wsdl:operation name="getEmployees">
Line:167  
Line:168           <wsdlsoap:operation soapAction=""/>
Line:169  
Line:170           <wsdl:input name="getEmployeesRequest">
Line:171  
Line:172              <wsdlsoap:body use="literal"/>
Line:173  
Line:174           </wsdl:input>
Line:175  
Line:176           <wsdl:output name="getEmployeesResponse">
Line:177  
Line:178              <wsdlsoap:body use="literal"/>
Line:179  
Line:180           </wsdl:output>
Line:181  
Line:182        </wsdl:operation>
Line:183  
Line:184        <wsdl:operation name="updateEmployee">
Line:185  
Line:186           <wsdlsoap:operation soapAction=""/>
Line:187  
Line:188           <wsdl:input name="updateEmployeeRequest">
Line:189  
Line:190              <wsdlsoap:body use="literal"/>
Line:191  
Line:192           </wsdl:input>
Line:193  
Line:194           <wsdl:output name="updateEmployeeResponse">
Line:195  
Line:196              <wsdlsoap:body use="literal"/>
Line:197  
Line:198           </wsdl:output>
Line:199  
Line:200        </wsdl:operation>
Line:201  
Line:202        <wsdl:operation name="sendEmail">
Line:203  
Line:204           <wsdlsoap:operation soapAction=""/>
Line:205  
Line:206           <wsdl:input name="sendEmailRequest">
Line:207  
Line:208              <wsdlsoap:body use="literal"/>
Line:209  
Line:210           </wsdl:input>
Line:211  
Line:212           <wsdl:output name="sendEmailResponse">
Line:213  
Line:214              <wsdlsoap:body use="literal"/>
Line:215  
Line:216           </wsdl:output>
Line:217  
Line:218        </wsdl:operation>
Line:219  
Line:220     </wsdl:binding>
Line:221  
Line:222     <wsdl:service name="EmployeesDBService">
Line:223  
Line:224       <wsdl:port binding="impl:EmployeesDBSoapBinding" name="EmployeesDB">
Line:225  
Line:226           <wsdlsoap:address location=
                        "http://localhost:8080/EmployeeWS/services/EmployeesDB"/>
Line:227  
Line:228        </wsdl:port>
Line:229  
Line:230     </wsdl:service>
Line:231  
Line:232  </wsdl:definitions>

WSDL 文件中的代码很简单。EmployeesDB.java 文件有两个方法:

  • 其中一个方法是 getEmployees(),它连接到数据库并获取 employees 表中的所有值。然后创建一个 employee 对象列表,并填充它的字段 name 和 identifier。如图 7 所示。

    图 7. 数据库中的 Employee 表
    数据库中的 Employee 表
  • 另一个方法是 updateEmployee(),它将输入作为 XML 格式的字符串,然后将其解码为一个 “Employee” bean。最后使用 field 字段(该表的主键)更新 employee 表中的雇员名称。

要查看该 Web 服务的源代码,可以参考本文末尾的下载部分的 “EmployeesDB Web 服务的源代码”。

最后的步骤是将 portlet 应用程序部署到 WebSphere Portal 服务器。该 portlet 类似于图 8。

图 8. 在 Internet Explorer 浏览器中显示的 FlexWebService portlet
在 Internet Explorer 浏览器中显示的 FlexWebService portlet

使用 JSON

JavaScript Object Notation(通常称为 JSON)是一种轻量级的数据交换格式。它不仅便于人类的读写,还便于计算机解析和生成。JSON 基于于 1999 年 12 月发布的 JavaScript Programming Language, Standard ECMA-262 Third Edition 的一部分。JSON 是完全独立于语言的文本格式,但融入了 C 语言家族的程序员的使用习惯,比如 C、C++、C#、Java、JavaScript、Perl 和 Python 等。这些特征使 JSON 成为一种理想的数据交换语言。

JSON 构建在两个结构之上:

  • 名称-值对集合。这个集合可能被实现为对象、记录、结构、词典、散列表、键列表或关联数组,具体情况取决于所使用的语言。
  • 值的有序列表。在大多数语言中,这个列表被实现为数组、向量、列表或序列。

这两个结构是通用的数据结构。几乎所有的现代语言都以这种或那种方式支持它们。一种既可以在不同的编程语言之间交换、又基于这种结构的数据格式是非常有意义的。

Ajax 是一种 Web 开发技术,对于每个请求,它支持客户端脚本仅从服务器获取所需的数据而不是获取完整的 Web 页面来加快服务器的响应速度,这种方法将需要从服务器传输的数据减至最少。

这些请求通常获取 XML 格式的响应,随后 XML 数据被解析为 JavaScript 代码以呈现结果,该过程让 JavaScript 代码变得更加复杂。

JSON 的构思是用 Java 代码可以轻松解析的数据结构表示响应。

JSON 有几个优势:

  • 它是轻量级的数据交换格式。
  • 它便于人类读写。
  • 它便于计算机解析和生成。
  • 可以使用 JavaScript 中的普通 eval() 过程解析它。
  • 它支持 ActionScript、C、C#、ColdFusion、E、Java、JavaScript、ML、Objective CAML、Perl、PHP、Python、Rebol、Ruby 和 Lua。

运行的 Adobe Flex 在 WebSphere Portal portlet 中调用 JSON 对象

在这个例子中,您可以了解如何运行 Adobe Flex 应用程序。Flex 应用程序调用在门户应用程序的后端 servlet 中注册的 JSON 对象。JSON servlet 从数据库获取对象。Flex 应用程序还提供一个用于更新数据表格的表单。在提交该表单时,将调用 JSON servlet 中的 update 函数并同步数据库。

遵循以下步骤构建一个 portlet 应用程序:

  1. 打开 Rational Software Architect。
  2. 选择 File - New - Project。
  3. 在显示的 New Project 窗口中,展开 Portal 文件夹并选择 Portlet Project。然后单击 Next。
  4. 在显示的 New Portlet Project 窗口中执行以下操作:

    • 在 Project name 字段输入 FlexJSONPortlet。这将创建一个基础的 portlet,它扩展了在 Java Portlet Specification Version 1.0 (JSR 168) 中定义的 GenericPortlet 类。
    • 选择 WebSphere Portal V6.0 作为 Target RunTime。
    • 在 EAR Membership 部分使用默认设置。
    • 在 Portlet API 字段中选择 JSR 168 Portlet。
    • 在 Create a portlet 部分使用默认设置。
    • 取消选择 Show advanced settings 选项。

    单击 Next。

    图 9. 定义 portlet 项目
    定义 portlet 项目
  5. 在显示的 Project Facets 窗口中,选择以下选项作为默认设置:

    • Dynamic Web Module
    • Java
    • JSR 168 Portlets
    • JSR 168 Portlets on WebSphere Portal

    单击 Next 接受默认选项。如图 10 所示。

    图 10. Project Facets
    Project Facets
  6. 在显示的 Portlet Settings 窗口中,选择了以下的默认设置:

    • 对于内容类型和模式,text/html 是内容类型,view 是模式。
    • 选择了 Generate a custom portlet class 选项,默认的 Package prefix 被设置为 com.ibm.flexwebservice,默认的 Class prefix 被设置为 FlexWebServicePortlet。
    • 在 locale-specific information 部分,默认选择 en。

    通过单击 Next 接受默认值。如图 11 所示。

    图 11. Portlet Settings 窗口
    Portlet Settings 窗口
  7. 在显示的 Action and Preferences 窗口中,取消选择所有选项并单击 Finish。
  8. 打开 FlexJSONPortlet 项目,右键单击 WebContent 文件夹。创建一个名为 movies 的新文件夹。FlexWebService portlet 的文件夹结构类似于图 12。

    图 12. 添加 movies 文件夹之后的文件夹结构
    添加 movies 文件夹之后的文件夹结构
  9. 接下来,修改包含在 com.ibm.flexjsonportlet 包中的 portlet 类 FlexJSONPortlet 以让它调用 doView() 方法中的 FlexJSONPortletView.jsp,如清单 6 所示。
清单 6. FlexJSONPortlet.java
Line:1    package com.ibm.flexjsonportlet;
Line:2    
Line:3    import java.io.*;
Line:4    import javax.portlet.*;
Line:5    
Line:6    public class FlexJSONPortlet extends GenericPortlet {
Line:7    	
Line:8    	public static final String JSP_FOLDER    = "/_FlexJSONPortlet/jsp/";   
                // JSP folder name
Line:9    	public static final String VIEW_JSP      = "FlexJSONPortletView";         
                // JSP file name to be rendered on the view mode
Line:10   
Line:11   	public void doView(RenderRequest request, RenderResponse response) 
                throws PortletException, IOException {
Line:12   		// Set the MIME type for the render response
Line:13   		response.setContentType(request.getResponseContentType());
Line:14   
Line:15   		// Invoke the JSP to render
Line:16   		PortletRequestDispatcher rd =  
                    getPortletContext().getRequestDispatcher
                    (getJspFilePath(request, VIEW_JSP));
Line:17   		rd.include(request,response);
Line:18   	}
Line:19   
Line:20   	private static String getJspFilePath(RenderRequest request, 
                String jspFile) {
Line:21   		String markup = request.getProperty("wps.markup");
Line:22   		if( markup == null )
Line:23   			markup = getMarkup(request.getResponseContentType());
Line:24   		return JSP_FOLDER + markup + "/" + jspFile + "." 
                    + getJspExtension(markup);
Line:25   	}
Line:26   
Line:27   
Line:28   	private static String getMarkup(String contentType) {
Line:29   		if( "text/vnd.wap.wml".equals(contentType) )
Line:30   			return "wml";
Line:31           else
Line:32               return "html";
Line:33   	}
Line:34   
Line:35   	private static String getJspExtension(String markupName) {
Line:36   		return "jsp";
Line:37   	}
Line:38   
Line:39   }
  1. 在 _FlexJSONPortlet/jsp/html 文件夹中可以找到 FlexJSONPortletView.jsp。在 div 标记内部定义 OBJECT 和 EMBED 标记,如清单 6 的 26 至 43 行所示。在第 18 至 21 行中,有一个从 Flex 应用程序调用的 getURL Javascript。JS 函数为 JSON servlet 返回 URL。如清单 7 所示。
清单 7. FlexJSONPortletView.jsp
Line:1    <%@page session="false" contentType="text/html" pageEncoding="ISO-8859-1" 
             import="java.util.*,javax.portlet.*,com.ibm.flexjsonportlet.*" %>
Line:2    <%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
Line:3    <portlet:defineObjects/>
Line:4    
Line:5    
Line:6    <style type="text/css">
Line:7    		#fxJavaScript { width: 90%; height: 500px; }
Line:8    		#html_controls {width: 15em; margin-top: 1em; padding: 1em;
Line:9    				color: white; border: solid 1px white;
Line:10   				font-family: Arial
Line:11   		}
Line:12   		body>#html_controls {	width: 13em;}
Line:13   		body {background-color: #869CA7;}
Line:14   </style>
Line:15   
Line:16   
Line:17   <script language="JavaScript">
Line:18   		function getURL() {		   
Line:19   		    var urlString = "<%=renderResponse.encodeURL
                        (renderRequest.getContextPath()+"/JSONServlet")%>";
Line:20   		    return urlString;	
Line:21   		}		
Line:22   </script>
Line:23   
Line:24   <div>
Line:25         
Line:26   	<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
Line:27   			id="jsonrpcserializing" width="100%" height="500px"
Line:28   			codebase="http://fpdownload.macromedia.com/get/
                        flashplayer/current/swflash.cab">
Line:29   			<param name="movie" value="<%=renderResponse.encodeURL
                        (renderRequest.getContextPath()+
                        "/movies/jsonrpcserializing.swf")%>" />
Line:30   			<param name="quality" value="high" />
Line:31   			<param name="bgcolor" value="#869ca7" />
Line:32   			<param name="allowScriptAccess" value="sameDomain" />
Line:33   	<embed src="<%=renderResponse.encodeURL(renderRequest.getContextPath()+
                "/movies/jsonrpcserializing.swf")%>"
Line:34   			quality="high" bgcolor="#869ca7"
Line:35   			width="100%" height="500px" name="jsonrpcserializing" 
                        align="middle"
Line:36   				play="true"
Line:37   				loop="false"
Line:38   				quality="high"
Line:39   				allowScriptAccess="sameDomain"
Line:40   				type="application/x-shockwave-flash"
Line:41   				pluginspage=
                            "http://www.adobe.com/go/getflashplayer">
Line:42   			</embed>
Line:43   	</object>
Line:44   
Line:45   </div>

JSONServlet.java 有两个方法,它们是 doGet() 和 updateEmployee()。

  • doGet() 方法需要一个使用 JDBC 类的后端数据库,以及创建 JSONObject 对象并将其作为一个 JSONArray 连接起来。
  • updateEmployee() 方法检查当前 HTTP 请求中的 name 和 identifier 参数,以更新数据库。

请查看清单 8。

清单 8. JSONServlet.java
Line:1    package com.ibm.flexjsonportlet.json;
Line:2    
Line:3    import java.io.*;
Line:4    import java.sql.Connection;
Line:5    import java.sql.DriverManager;
Line:6    import java.sql.ResultSet;
Line:7    import java.sql.Statement;
Line:8    import javax.servlet.*;
Line:9    import javax.servlet.http.*;
Line:10   import org.json.JSONArray;
Line:11   import org.json.JSONObject;
Line:12   
Line:13   
Line:14   
Line:15   
Line:16   public class JSONServlet extends  HttpServlet{
Line:17   	  
Line:18       String url = "jdbc:mysql://localhost:3306/";
Line:19       String dbName = "flex";
Line:20       String driver = "com.mysql.jdbc.Driver";
Line:21       String userName = "root"; 
Line:22       String password = "admin";
Line:23       Connection conn = null;
Line:24       
Line:25       
Line:26     public void init(ServletConfig config) throws ServletException {
Line:27           super.init(config);
Line:28           try {
Line:29   		    Class.forName(driver).newInstance();
Line:30   			conn = DriverManager.getConnection(url+dbName,
                        userName,password);
Line:31   			System.out.println("Connected to the database");
Line:32   			    
Line:33           }catch (Exception e) {
Line:34   				e.printStackTrace();
Line:35   			}
Line:36           
Line:37     }
Line:38   
Line:39     public void doGet(HttpServletRequest request,HttpServletResponse response)
Line:40      throws ServletException,IOException{
Line:41   	  	
Line:42   	  	
Line:43           
Line:44           updateEmployee(request);
Line:45           JSONArray array=new JSONArray();
Line:46   	    try {
Line:47   	   
Line:48   		    Statement st = conn.createStatement();
Line:49   		    String query = "select * from employee";
Line:50   	        ResultSet rs = st.executeQuery(query);
Line:51   	        while (rs.next()){
Line:52   	        	JSONObject obj=new JSONObject();
Line:53   	        	obj.put("name", rs.getString("name")!=
                            null?rs.getString("name"):"");
Line:54   	        	obj.put("identifer", rs.getString("identifer")!=
                            null?rs.getString("identifer"):""); 
Line:55   	        	array.put(obj);
Line:56   	        }
Line:57   	        rs.close();
Line:58   			st.close();
Line:59   	        System.out.println("query excuted successfully!");
Line:60   	    } catch (Exception e) {
Line:61   		      e.printStackTrace();
Line:62   	    }
Line:63   	  
Line:64   	  
Line:65   	  PrintWriter out = new PrintWriter(response.getWriter(),true);
Line:66   	  out.println(array);
Line:67      
Line:68     }
Line:69     
Line:70   	public void updateEmployee(HttpServletRequest request) {
Line:71   	 try{
Line:72   		String name=request.getParameter("name");
Line:73   		String identifer=request.getParameter("identifer");
Line:74   		if (name!=null && identifer!=null){
Line:75   			Statement st = conn.createStatement();
Line:76   			st.executeUpdate ("update employee set name = 
                        '"+name+"', " +
Line:77   				"identifer = "+identifer+
Line:78   				"where identifer = "+identifer+" ");
Line:79   			 st.close ();
Line:80   			 System.out.println(name +" - "+ identifer);
Line:81   		   }
Line:82   		}catch(Exception ex){ex.printStackTrace();}
Line:83   		
Line:84   	}
Line:85   }
  1. 根据清单 9 修改 web.xml 文件。
清单 9. web.xml
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>
	FlexJSONPortlet</display-name>
	<servlet>
		<description>
		</description>
		<display-name>
		JSONServlet</display-name>
		<servlet-name>JSONServlet</servlet-name>
		<servlet-class>
		com.ibm.flexjsonportlet.json.JSONServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>JSONServlet</servlet-name>
		<url-pattern>/JSONServlet</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<jsp-config>
		<taglib>
			<taglib-uri>http://java.sun.com/portlet</taglib-uri>
			<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
		</taglib>
	</jsp-config>
</web-app>
  1. 打开 Adobe Flex Builder 并创建一个新的 Flex 项目。
    Mbr/>

    在显示的 New Flex Project 窗口中,在 Project name 字段输入 jsonrpcserializing,接受所有默认设置并单击 Finish。

    现在,项目的文件夹类似于图 13。

    图 13. Flex 项目的结构
    Flex 项目的结构
  2. 根据清单 10 修改 jsonrpcserializing.mxml 文件。清单 10 逐行解释了这些代码。
清单 10. jsonrpcserializing.mxml
Line:1    <?xml version="1.0" encoding="utf-8"?>
Line:2    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" 
             layout="horizontal"
Line:3    	creationComplete="onCreationComplete()">
Line:4    	
Line:5    	<mx:HTTPService id="service" resultFormat="text"
Line:6    			result="onLoad(event)" />
Line:7    
Line:8    
Line:9    		<mx:Script>
Line:10   	       <![CDATA[
Line:11   	        
Line:12   		import mx.rpc.events.*;
Line:13   		import com.adobe.serialization.json.JSON;
Line:14   		import mx.rpc.events.ResultEvent;
Line:15   		import mx.controls.Alert;
Line:16   		import mx.collections.ArrayCollection;
Line:17   		import flash.external.ExternalInterface;
Line:18   	
Line:19   		private function onCreationComplete():void {
Line:20   			if (!ExternalInterface.available)
Line:21   				 Alert.show( "No ExternalInterface available 
                            for container" );
Line:22   			callJavaScript();
Line:23   					
Line:24   			}
Line:25   				
Line:26   		 private function callJavaScript():void {
Line:27   			if (!ExternalInterface.available) 
Line:28   			return;
Line:29   				var retVal:Object = ExternalInterface.call
                            ("getURL","");
Line:30   				var urlString:String = retVal as String;
Line:31   				service.url = urlString;
Line:32   				service.send();
Line:33   			}
Line:34   				
Line:35   		private function onLoad(event:ResultEvent):void {
Line:36   		//get the raw JSON data and cast to String
Line:37   		var rawData:String = String(event.result);
Line:38   	
Line:39   		//decode the data to ActionScript using the JSON API
Line:40   		//in this case, the JSON data is a serialize Array of Objects.
Line:41   		var arr:Array = (JSON.decode(rawData) as Array);
Line:42   	
Line:43   		//create a new ArrayCollection passing the de-serialized Array
Line:44   		//ArrayCollections work better as DataProviders, as they can
Line:45   		//be watched for changes.
Line:46   		var dp:ArrayCollection = new ArrayCollection(arr);
Line:47   	
Line:48   		//pass the ArrayCollection to the DataGrid as its dataProvider.
Line:49   		myGrid.dataProvider = dp;
Line:50   		profitPie.dataProvider = dp;
Line:51   		}
Line:52   				
Line:53   		private function choosenItem(selectedItem:Object):void {
Line:54   		        	            formPanel.visible  =  false;
Line:55   		employeeObj.name      = selectedItem.name;
Line:56   		employeeObj.identifer = selectedItem.identifer;
Line:57   		formPanel.visible 	  = true;
Line:58   		formPanel.setStyle("showEffect","fadeIn");
Line:59   		 }
Line:60   				  
Line:61   			 private function submitForm():void {
Line:62   			   //Alert.show(employeeObj.name);
Line:63   			   service.send(employeeObj);
Line:64   			}
Line:65   	
Line:66   	        ]]>
Line:67   	    </mx:Script>
Line:68   
Line:69   	    <mx:Fade id="fadeIn" duration="1000" alphaFrom="0.0" 
                    alphaTo="1.0"/>
Line:70   	    
Line:71   		<mx:Panel title="Employees" width="100%" height="100%">
Line:72   		<mx:DataGrid id="myGrid" labelField=
                    "{choosenItem(myGrid.selectedItem)}" width="100%" height="50%"> 
Line:73   				<mx:columns>
Line:74   				<mx:DataGridColumn headerText="name" 
                            dataField="name" />
Line:75   				<mx:DataGridColumn headerText="identifer" 
                            dataField="identifer" />
Line:76   	    		</mx:columns>
Line:77   		</mx:DataGrid>
Line:78   		<mx:PieChart id="profitPie"  showDataTips="true" width="100%" 
                      height="50%">
Line:79   	      	<mx:series>
Line:80   	        	<mx:PieSeries field="identifer" nameField="name" 
                                 labelPosition="callout" />
Line:81   	      		</mx:series>
Line:82   	    	</mx:PieChart>
Line:83   		</mx:Panel>
Line:84   		
Line:85   		
Line:86   		<mx:Model id="employeeObj">
Line:87   			<root>
Line:88   				<name>{employeeName.text}</name>
Line:89   				<identifer>{identifer.text}</identifer>
Line:90   			</root>
Line:91   		</mx:Model>
Line:92   		
Line:93   		<mx:Panel id="formPanel" title="Form" width="100%" height="10%" 
                    visible="false" showEffect="{fadeIn}">	
Line:94   			<mx:Form width="100%"> 
Line:95   				<mx:FormItem label="Name">
Line:96   					<mx:TextInput id="employeeName" 
                                text="{employeeObj.name}"/>
Line:97   				</mx:FormItem>
Line:98   				<mx:FormItem label="Identifer">
Line:99   				<mx:TextInput id="identifer" editable="false" 
                            text="{employeeObj.identifer}"/>
Line:100  				</mx:FormItem>
Line:101  			</mx:Form>
Line:102  	
Line:103  			<mx:ControlBar>
Line:104  				<mx:Button buttonDown="true" label="Update" 
                            click="submitForm()"/>
Line:105  			</mx:ControlBar>
Line:106  		</mx:Panel>
Line:107  
Line:108  </mx:Application>

第 2 至 3 行显示应用程序标记 mx:Application。Flex 定义了一个默认的应用程序容器,您可以通过它为应用程序添加内容,而不需显式地定义其他容器。您可以将布局指定为水平对齐,这意味着 movie 中包含的两个面板是相邻的。此外,您还可以对 CreationComplete 事件调用 onCreationComplete() 函数。CreationComplete 是在整个组件(及其子组件)完全创建之后、在组件的生命周期的末尾触发的。

第 19 至 24 行显示 onCreationComplete 函数的声明。在这个函数中,您检查被声明的 ExternalInterface 实例并调用 callJavaScript() 函数。

第 26 至 33 行调用返回 JSON servlet 的内联 getURL() 函数。此外,它还定义 HTTP 服务的 URL 属性,并最终使用 send() 方法调用服务。

第 35 至 51 行显示为 HTTPservice 注册的 onLoad() 函数。这个函数在调用 HTTP 服务之后调用。onLoad() 函数获取原始的 JSON 数据并将其强制转换成 String,使用 JSON API 将数据解码为 ActionScript(在本例中 JSON 数据是一个序列化的对象数组),并创建一个传递反序列化 Array 的新 ArrayCollection。ArrayCollection 函数作为 DataProviders 能够更好地发挥作用,因为可以监视它们的更改。最后,将 ArrayCollection 作为 DataGrid 的 dataProvider 传递给它。

第 53 至 60 行显示数据表的 label 函数。chosenItem 函数传递在数据表格中选择的整个行。您将该行的值绑定到 employee 模型。

返回来,employee 模型将绑定到表单字段。第 58 行显示了如何为表单添加渐退效果。

第 61 至 64 行显示了 submitForm() 函数。该函数在单击 Update 按钮时调用。

第 71 至 83 行显示数据表格和一个嵌入到标题为 Employees 的面板中的饼图。数据表格有两个列,即 name 和 identifier。您可以使用 PieSeries 图表系列和 PieChart 控件为该图表定义数据。将标识符指定为一个字段属性,让图表知道使用哪个值来创建大小适合的楔形饼图。

第 94 至 101 行显示了用于更新雇员数据的表单。注意,在 showEffect="{fadeIn}" 字段中添加了 “fadeIn” 效果,它显示应用程序的工作流。可以在第 69 行中找到渐退效果的声明和属性。

第 103 至 106 行显示了 Update 按钮。遇到单击事件时,它将调用 submitForm() 函数并传递可以绑定到表单字段 name 和 identifier 的 employee 模型。

  1. 单击 Export Release Build 按钮 Export Release Build 按钮 添加 bin-release 文件夹。在该文件夹中可以找到 jsonrpcserialization.swf 短片,需要使用它将 jsonrpcserialization.swf 文件移动到先前创建的 movies 文件夹中的 portlet 项目。如图 14 所示。

    图 14. jsonrpcserialization 项目的文件夹结构
    jsonrpcserialization 项目的文件夹结构
  2. 让我们返回到门户项目并运行它。您的 portlet 类似于图 15。

    图 15. 在 Internet Explorer 浏览器中显示的 FlexJSON portlet
    在 Internet Explorer 浏览器中显示的 FlexJSON portlet

结束语

Adobe Flex 是一款可以交付富 Internet 应用程序的新工具。Adobe Flex 是可以跨浏览器和平台应用的客户端解决方案。Adobe Flex 为门户应用程序提供许多优势,比如在浏览器上更新信息而不需要刷新整个页面。在门户环境中,为了使用某项功能而刷新整个页面需要占用大量网络资源并损害整体性能。Adobe Flex 通过其嵌入式 SOA 代理客户端和嵌入式 JSON 适配器在门户框架中提供丰富的功能。本文通过两个例子演示如何将 Adobe Flex 集成到 WebSphere Portal 中,并逐行解释了例子中的代码。您可以使用 Flex 呈现 portlet 用户界面、克服 HTML 的限制和显著改善用户的门户体验。


下载

描述名字大小
EmployeesDB Web 服务的源代码EmployeeWS.zip2578KB
FlexWebService portlet 的项目附件FlexWebServicePortal.zip721KB
WebServiceFlex 应用程序的源代码WebServiceFlex.zip14KB
jsonrpcserialization 的源代码jsonrpcserializing.zip1332KB
FlexJsonPortlet 的源代码FlexJSONPortlet.zip1154KB

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=466863
ArticleTitle=集成 Adobe Flex 和 IBM WebSphere Portal
publish-date=02082010