- 浏览: 101518 次
- 性别:
- 来自: 合肥
文章分类
最新评论
-
薛木木:
能说一下怎么解决的吗?没看懂哇。。。谢谢
socket.sendUrgentData在windows7下出现17次失效的问题 -
coral0212:
基于代理模式实现权限管理的案例举例说明数据权限如下:例1:论坛 ...
代理模式 -
coral0212:
面向对象设计原则:1.开闭原则2.少用继承,多用聚合3.针对接 ...
代理模式 -
zengshaotao:
jackyin5918 写道你好,你可曾 研究过 obj[p] ...
javascript遍历对象属性和方法 -
muhengji:
处理一下,具体是怎么处理呢,求指教。
socket.sendUrgentData在windows7下出现17次失效的问题
Exchanging Complex Data with Back-End Systems
Christophe Coenraets
Adobe
Retrieving server data in a Macromedia Flex application is generally easy and demonstrated in many sample applications. Sending complex data back to the server can be slightly more involved, however.
Depending on your role, and on the structure of your development team, you may have the luxury to choose—or at least influence—the architecture used to exchange data between the client and the server: web services, XML over HTTP, or remote method invocation.
In a service-oriented architecture, however, it is also likely that your application will have to access services that you didn't build and over which you have no control. In that case, you have to use the data exchange architecture implemented by the service provider.
This article takes a close look at different strategies to send complex data to the server using the three data services available in Flex to accommodate the heterogeneous data access requirements of your application: HTTPService, RemoteObject, and WebService.
Requirements
To complete this tutorial you will need to install the following software and files:
Macromedia Flex
Macromedia Flash Player
A text editor or Macromedia Flex Builder
Tutorials and sample files:
- complexdata.zip (ZIP, 23K)
Prerequisite knowledge:
Basic experience with the Flex programming model and application framework.
Using HTTPService
There are two commonly used approaches to send data to the server using the HTTPService:
- Passing request parameters
- Sending XML over HTTP
Passing Request Parameters
The request-parameters approach works fine for simple data. In the Employee Directory application (see Figure 1), we send basic employee information (first name, last name, salary, and start date) to a JavaServer page.
Here is the source code for the simple Employee Directory application:
employeehttp.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" backgroundColor="#FFFFFF"> <mx:HTTPService id="srv" url="employeehttp.jsp" method="POST"> <mx:request> <firstName>{firstName.text}</firstName> <lastName>{lastName.text}</lastName> <salary>{salary.text}</salary> <startDate>{startDate.text}</startDate> </mx:request> </mx:HTTPService> <mx:Form> <mx:FormItem label="First Name"> <mx:TextInput id="firstName"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lastName"/> </mx:FormItem> <mx:FormItem label="Salary"> <mx:TextInput id="salary"/> </mx:FormItem> <mx:FormItem label="Start Date"> <mx:DateField id="startDate"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Add Employee" click="srv.send()"/> </mx:FormItem> </mx:Form> </mx:Application>
At the server side, it's business as usual: You access the request parameters using the traditional API provided by your server-side language. Here is a JSP example:
employeehttp.jsp
<% String firstName= request.getParameter("firstName"); String lastName= request.getParameter("lastName"); String salary= request.getParameter("salary"); String startDate= request.getParameter("startDate"); // Some business logic to process the data %> <status>ok</status>
One advantage of this approach is that, from the server point of view, it works exactly like an HTML front end. This makes it particularly easy to replace an HTML-based user interface with a Flex front end.
In HTML, the request parameters approach works fine, mainly because the client side of the application is stateless and because the data-entry process is split across multiple pages. Therefore the data submitted to the server in one single request is never overly complex.
By contrast, a Flex application is stateful; the data-entry process is not constrained by the page-centric nature of HTML. You use rich user interface components to allow users to enter more complex data in a single integrated user interface. For example, Figure 2 represents an improved version of the Employee Directory application in Figure 1, where users can enter an unlimited number of phone numbers for an employee.
With the availability of more sophisticated user interfaces, you will often need to submit more complex data to the server in one single request than you do in HTML. When the complexity of the data increases, the request-parameters approach becomes cumbersome. In that case, sending an XML document is usually a better approach.
Sending XML Over HTTP
There are two major approaches to sending XML data over HTTP:
- Sending XML as a request parameter
- Sending XML in an "application/xml" request
Sending XML as a Request Parameter: The code below provides an implementation of the Employee Directory application, where data is sent to the server in an XML string passed as a request parameter:
employeexml.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" backgroundColor="#FFFFFF" initialize="initApp()"> <mx:Script> var employee: Employee; function initApp() { employee=new Employee(); employee.phoneNumbers=new Array(); } function addEmployee() { employee.firstName=firstName.text; employee.lastName=lastName.text; employee.startDate=startDate.selectedDate; employee.salary=Number(salary.text); srv.send({xml: XMLUtil.as2xml(employee, "employee")}); } </mx:Script> <mx:HTTPService id="srv" url="employeexml.jsp" method="POST"/> <mx:Form> <mx:FormItem label="First Name"> <mx:TextInput id="firstName"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lastName"/> </mx:FormItem> <mx:FormItem label="Salary"> <mx:TextInput id="salary"/> </mx:FormItem> <mx:FormItem label="Start Date"> <mx:DateField id="startDate"/> </mx:FormItem> <mx:FormItem label="Phone Numbers" verticalGap="1"> <mx:DataGrid id="dg" editable="true" dataProvider="{employee.phoneNumbers}"> <mx:columns> <mx:Array> <mx:DataGridColumn columnName="type" headerText="Type" cellRenderer="PhoneTypeRenderer"/> <mx:DataGridColumn columnName="number" headerText="Number"/> </mx:Array> </mx:columns> </mx:DataGrid> <mx:HBox horizontalGap="1" width="100%" horizontalAlign="right"> <mx:Button label="+" cornerRadius="0" borderThickness="0" width="20" height="20" click="dg.addItem(new PhoneNumber('H'))"/> <mx:Button label="-" cornerRadius="0" borderThickness="0" width="20" height="20" click="dg.removeItemAt(dg.selectedIndex)" /> </mx:HBox> </mx:FormItem> <mx:FormItem> <mx:Button label="Add Employee" click="addEmployee()"/> </mx:FormItem> </mx:Form> </mx:Application>
Notice that the application uses a simple object-to-XML conversion utility. Here is its source code:
XMLUtil.as
class XMLUtil { static function as2xml(obj: Object, nodeName: String) { var xml:XML=new XML(); xml.appendChild(xml.createElement(nodeName)); for (var i in obj) { handleItem(xml, obj[i], i); } return xml; } private static function handleItem(xml, item, nodeName: String) { var type=typeof item; if (type=="string" || type=="number" || item instanceof Date) { var el=xml.createElement(nodeName); el.appendChild(xml.createTextNode(item)); xml.firstChild.appendChild(el); } else if (item instanceof Array) { for(var i=0; i<item.length; i++) handleItem(xml, item[i], nodeName); } else if (item instanceof Object) xml.firstChild.appendChild(as2xml(item, nodeName)); } }
The Employee.as and PhoneNumber.as classes used in the application are defined as follows:
class Employee { public var firstName : String; public var lastName : String; public var salary : Number; public var startDate : Date; public var phoneNumbers : Array; } class PhoneNumber { public var number : String; public var type : String; function PhoneNumber(type: String) { this.type=type; } }
In this example, the benefits of first loading the data in an ActionScript object (Employee.as) before creating the XML document might not be obvious. However, in Flex applications, you are typically manipulating data as objects. (Even when you retrieve an XML document from the server using the HTTPService, the data is deserialized into an object graph by default.) So when you use the HTTPService, the need to convert objects to XML is a very common scenario.
At the server side, you access the "xml" request parameter using the API provided by the language you are using. You then typically use the XML parsing API provided by that language to process the information further. Here is a JSP example:
employeexml.jsp
<% String xml=request.getParameter("xml"); // Some business logic to process the data %> <status>ok</status>
Sending XML in an "application/xml" Request: To use this approach, just add contentType="application/xml"
to the HTTPService tag definition in employeexml.mxml, and replace the following:
srv.send({xml: XMLUtil.as2xml(employee, "employee")});
with this:
srv.send(XMLUtil.as2xml(employee, "employee"));
At the server side, your application now needs to handle an "application/xml" request. To do so, you typically use an input stream to read the incoming request. You then parse the received XML document using the parsing API provided by your server-side language. Here is a JSP example:
<%@ page import="java.io.BufferedReader, javax.xml.parsers.DocumentBuilderFactory, javax.xml.parsers.DocumentBuilder, org.w3c.dom.Document, org.xml.sax.InputSource"%> <% BufferedReader br = new BufferedReader(request.getReader()); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder db = factory.newDocumentBuilder(); Document doc = db.parse(new InputSource(br)); // Process the XML document %> <status>ok</status>
One nice feature of Flex when you use "application/xml" requests is that you actually don't have to perform the object-to-XML transformation yourself. You can provide an object as the request content and let Flex convert it automatically to XML.
To use the automatic object-to-XML encoding in the Employee Directory application, replace the following:
srv.send(XMLUtil.as2xml(employee, "employee"));
with this:
srv.send(employee);
Flex also allows you to substitute the default encoding logic with your own logic by providing an implementation for the xmlEncode()
method of the HTTPService. For example, to substitute the default encoding logic with the logic implemented in XMLUtil.as, add the following block of code to the initApp()
method:
srv.xmlEncode=function(obj: Object) { return XMLUtil.as2xml(obj, "data"); }
Using RemoteObject
The RemoteObject service allows you to invoke methods remotely in Java objects deployed in your application server. Flex.NET, currently in beta, will allow you to remotely invoke methods in .NET objects.
When invoking methods remotely, you can pass objects back and forth (as the methods' input parameters and return value) between the client and the server.
The RemoteObject approach makes particular sense when both the front end and the back end of your application manipulate data as objects. In this case, the intermediate step of converting objects to XML may result in unnecessary overhead.
When you use RemoteObject, Flex takes care of the serialization/deserialization process. The RemoteObject uses AMF (Action Message Format) over HTTP. AMF is a binary encoding format that makes this solution faster and leaner in terms of bandwidth usage than the other solutions, especially when manipulating large data sets.
In the RemoteObject implementation of the Employee Directory application, we use a Java class named EmployeeService. The EmployeeService class is defined as follows:
package samples.data; public class EmployeeService { public void addEmployee(EmployeeVO employee) { // Output data to console for demo purpose System.out.println("First Name: "+employee.getFirstName()); System.out.println("Last Name: "+employee.getLastName()); System.out.println("Salary: "+employee.getSalary()); System.out.println("Start Date: "+employee.getStartDate()); System.out.println("Phone Numbers:"); PhoneNumberVO[] phoneNumbers=employee.getPhoneNumbers(); PhoneNumberVO phoneNumber=null; for (int i=0; i<phoneNumbers.length; i++) { phoneNumber = phoneNumbers[i]; System.out.println(phoneNumber.getType()+": "+phoneNumber.getNumber()); } // Some business logic to process the data } }
The addEmployee()
method takes an EmployeeVO object as an argument. The EmployeeVO class is defined as follows:
package samples.data; import java.util.Date; public class EmployeeVO { private String firstName; private String lastName; private int salary; private Date startDate; private PhoneNumberVO[] phoneNumbers; // getter and setter methods not shown for brevity }
The PhoneNumberVO class referenced in EmployeeVO is defined as follows:
package samples.data; public class PhoneNumberVO { private String type; private String number; // getter and setter methods not shown for brevity }
When remotely invoking the addEmployee()
method in the client application, you need to make sure that the ActionScript object you pass as an argument is deserialized into an instance of the EmployeeVO class at the server side. Similarly, you need to make sure that the PhoneNumber objects you pass as part of the Employee object are deserialized into instances of the PhoneNumberVO class.
There are three basic rules to make sure an ActionScript object passed as a method parameter is deserialized into an instance of a specific Java class:
-
You need to declare the ActionScript/Java class mapping using the
Object.RegisterClass()
static function. For example:Object.registerClass("samples.data.EmployeeVO", samples.data.EmployeeVO);
The first argument is the fully qualified Java class name; the second argument is the ActionScript class.
- You have to provide the ActionScript class attributes with the exact same names (and same letter case) as the Java class attributes.
- You have to map the data types of the ActionScript class attributes to the data types of the Java class attributes. (Refer to the ActionScript/Java data type mapping table in the documentation for more details.)
In addition, even though it's not required, it's often considered a good practice to provide your ActionScript and Java classes with the same class and package names.
The same three rules also allow a Java object returned by remote method invocation to be deserialized into an object of a specific ActionScript class. (By default, an object returned from the server is deserialized into an instance of the ActionScript Object class.)
Here is the implementation of the Employee Directory using RemoteObject:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" backgroundColor="#FFFFFF" initialize="initApp()"> <mx:Script> import samples.data.*; var employee: EmployeeVO; function initApp() { employee=new EmployeeVO(); employee.phoneNumbers=new Array(); } function addEmployee() { employee.firstName=firstName.text; employee.lastName=lastName.text; employee.startDate=startDate.selectedDate; employee.salary=Number(salary.text); srv.addEmployee(employee); } </mx:Script> <mx:RemoteObject id="srv" source="samples.data.EmployeeService"> <mx:method name="addEmployee"/> </mx:RemoteObject> <mx:Form> <mx:FormItem label="First Name"> <mx:TextInput id="firstName"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lastName"/> </mx:FormItem> <mx:FormItem label="Salary"> <mx:TextInput id="salary"/> </mx:FormItem> <mx:FormItem label="Start Date"> <mx:DateField id="startDate"/> </mx:FormItem> <mx:FormItem label="Phone Numbers" verticalGap="1"> <mx:DataGrid id="dg" editable="true" dataProvider="{employee.phoneNumbers}" > <mx:columns> <mx:Array> <mx:DataGridColumn columnName="type" headerText="Type" cellRenderer="PhoneTypeRenderer"/> <mx:DataGridColumn columnName="number" headerText="Number"/> </mx:Array> </mx:columns> </mx:DataGrid> <mx:HBox horizontalGap="1" width="100%" horizontalAlign="right"> <mx:Button label="+" click="dg.addItem(new PhoneNumberVO('H'))" cornerRadius="0" borderThickness="0" width="20" height="20"/> <mx:Button label="-" click="dg.removeItemAt(dg.selectedIndex)" cornerRadius="0" borderThickness="0" width="20" height="20"/> </mx:HBox> </mx:FormItem> <mx:FormItem> <mx:Button label="Add Employee" click="addEmployee()"/> </mx:FormItem> </mx:Form> </mx:Application>
EmployeeVO.as is defined as follows:
class samples.data.EmployeeVO { public var firstName : String; public var lastName : String; public var phoneNumbers : Array; public var salary : Number; public var startDate : Date; static var registered= Object.registerClass("samples.data.EmployeeVO", samples.data.EmployeeVO); }
PhoneNumberVO.as is defined as follows:
class samples.data.PhoneNumberVO { public var number : String; public var type : String; static var registered= Object.registerClass("samples.data.PhoneNumberVO", samples.data.PhoneNumberVO); function PhoneNumberVO(type: String) { this.type=type; } }
Creating ActionScript classes based on existing Java classes can be a tedious and error-prone task. To facilitate my own development efforts, I created a simple utility that uses Java introspection to create automatically an ActionScript class based on a Java Value Object class. This utility, named java2as, is included in the supporting ZIP file in the Requirements section.
Using WebService
Just as with RemoteObject, when you invoke web services methods using the WebService component, you can pass objects back and forth (as the methods' input parameters and return value) between the client and the service.
To implement the Employee Directory application using the WebService approach, we will expose the EmployeeService class used in the RemoteObject example as a web service.
You can use your own web services engine to expose the EmployeeService class as a web service. If you use Axis, add the following service declaration to WEB-INF\server-config.wsdd:
<service name="EmployeeService" provider="java:RPC"> <parameter name="methodName" value="*"/> <parameter name="className" value="samples.data.EmployeeService"/> <beanMapping languageSpecificType="java:samples.data.EmployeeVO" qname="ns5:EmployeeVO" xmlns:ns5="http://www.macromedia.com/samples"/> <beanMapping languageSpecificType="java:samples.data.PhoneNumberVO" qname="ns6:PhoneNumberVO" xmlns:ns6="http://www.macromedia.com/samples"/> </service>
Note: Make sure that the ns:<number>
you use for each beanMapping
is unique within the WSDD file.
The web service's WSDL file describes the methods available as well as the complex data types used in the service. If you use Axis, you can access the WSDL file using the following URL:
http://localhost:8700/flex/services/EmployeeService?wsdl
Here are two interesting sections of the WSDL file for the EmployeeService web service:
The method declaration:
<wsdl:message name="addEmployeeRequest"> <wsdl:part name="employee" type="tns1:EmployeeVO" /> </wsdl:message>
The complex data types declaration:
<complexType name="PhoneNumberVO"> <sequence> <element name="number" nillable="true" type="xsd:string" /> <element name="type" nillable="true" type="xsd:string" /> </sequence> </complexType> <complexType name="EmployeeVO"> <sequence> <element name="firstName" nillable="true" type="xsd:string" /> <element name="lastName" nillable="true" type="xsd:string" /> <element name="phoneNumbers" nillable="true" type="impl:ArrayOf_tns1_PhoneNumberVO" /> <element name="salary" type="xsd:int" /> <element name="startDate" nillable="true" type="xsd:dateTime" /> </sequence> </complexType>
When you remotely invoke the addEmployee()
method on the web service, your only requirement is to pass an ActionScript object whose attributes' names and data types match the complexType definition in the WSDL file. (Refer to the ActionScript/Web Services data type mapping table in the documentation for more details.)
To implement the Employee Directory using the WebService approach, simply replace the RemoteObject declaration with a WebService declaration:
<mx:WebService id="srv" wsdl="@ContextRoot()/services/EmployeeService?wsdl"> <mx:operation name="addEmployee"/> </mx:WebService>
In this case, you don't have to define a class mapping using Object.registerClass()
. This means that you could also use the Employee and PhoneNumber class used in the HTTP example.
Summary
Flex provides three data services to accommodate the heterogeneous data access requirements of your application: HTTPService, RemoteObject, and WebService. Retrieving server data in a Flex application is generally easy. Sending complex data back to the server can be slightly more involved.
The HTTPServices allows you to send complex data to the server using XML over HTTP.
The RemoteObject service allows you to invoke methods remotely in Java objects deployed in your application server, and pass objects back and forth (as the methods' input parameters and return value) between the client and the server.
Similarly, the WebService component allows you to invoke web services methods and exchange complex data types between the client and the service.
发表评论
-
firefox不支持attachEvent的解决方法
2011-05-05 14:36 3578第一种方法,就是通过修改Object原型的方法来申明一个att ... -
Ext oop 基础
2010-08-05 14:03 1246轻松搞定Extjs[连载]——第三章:Ext OOP基础 ... -
用一个HelloWorl例子手把手教会你使用BlazeDS
2009-11-05 14:10 1097发表于: 2009-10-26 23:00:13 - IP:5 ... -
javascript遍历对象属性和方法
2009-07-30 16:35 22113javascript遍历对象属性和方法 functi ... -
flex使用RemoteObject,如何给服务器端传递对象
2008-11-28 13:15 4156关键字: flex 举个例子吧,比 ... -
简单的ext 登录界面 (含验证码)
2008-11-28 11:45 3534以下是一个简单的 ext 登录界面: 1. ... -
flex 如何用HTTPService 与后台交互数据
2008-11-28 11:20 2580<?xml version="1.0" ... -
EXT 方法集锦
2008-11-28 11:11 2809EXT 方法集锦 (后续添加中) 1. ext的 ... -
Flex 2实现文件上传
2008-11-27 21:06 1631Flex 2实现文件上传 ... -
flex 技巧集锦
2008-11-27 21:00 1303Flex编程小技巧集锦 关键词: FLEX ... -
java flex servlet 通讯
2008-11-27 20:55 2788自从呼叫中心项目开始 ... -
Flex编程模型
2008-11-26 19:12 1101Flex编程模型 Flex包含Flex ...
相关推荐
The purpose of 2017 International Conference on Security with Intelligent Computing and Big-data Services (SICBS’17 for short) with joined workshops, Workshop on Information and Communication ...
为了解决这些问题,研究者提出了ELEGANT(Exchanging Latent Encodings with Generative Adversarial Networks for Transferring Multiple Face Attributes)模型。 ELEGANT模型的核心是利用生成对抗网络(GAN)来...
The encryption device performs optical character recognition (OCR) and interprets the data Choose an appropriate key from an SD card to decrypt the message. You would choose a key that you pre-...
- **XML (Chapter 20):** XML is a standard format for exchanging data. This chapter teaches how to parse and generate XML using the built-in XML support in F#. - **ASP.NET MVC (Chapter 21):** ASP.NET ...
标题 "Flex3GSE_ExchangingData_JSP" 涉及到的是使用Adobe Flex与Java Server Pages (JSP) 进行数据交换的技术。Flex是一款用于构建富互联网应用程序(RIA)的开发工具,它主要使用ActionScript编程语言,而JSP是...
Exchanging messages with a SMTP server 16-3. whois_request() function 16-4. Simple whois frontend (HTML code) 16-5. Simple whois frontend (PHP code) 16-6. Source code of the simple whois front-end 16...
2. **Graph Data Processing**: Methods for handling and querying graph-structured data, which is crucial for social network analysis and complex relationships. 3. **Data Mining**: Algorithms and ...
- FIX: The height of the TFlexRegularPolygon object incorrectly changes with its rotation. - FIX: Added division by zero protect in method TFlexControl.MovePathSegment. - FIX: The background beyond ...
标题中的"A simple example of exchanging data across a network using t"似乎是指使用特定技术(可能是WinSock)在网络间交换数据的一个简单示例。这个示例可能是针对初学者或开发者,旨在教授如何利用网络通信类...
The Salesforce Integration Patterns and Practices document is a valuable resource for developers and architects looking to integrate Salesforce with other systems. By following the patterns outlined ...
Flex3+php+mysql data exchanging quick guild 博文链接:https://corelengine.iteye.com/blog/231718
- **Serialization:** Serialization is crucial for exchanging data between actors. Akka supports various serialization formats, including binary and JSON. - **I/O:** Akka I/O provides a non-blocking ...
DAG, a data structure upon which one can build versioned file systems, blockchains, and even a Permanent Web. IPFS combines a distributed hashtable, an incentivized block exchange, and a self-...
3. Spring in the back end Chapter 10. Hitting the database with Spring and JDBC 10.1. Learning Spring’s data-access philosophy 10.1.1. Getting to know Spring’s data-access exception hierarchy 10.1.2...
This VB6 code cleans the ILOVEYOU virus from systems<END> 38 , shras21.zip Custom Control, that lets you have full control of Dial Up Networking<END> 39 , FullBrowser.zip : This is A ...
- **Importing and Exporting**: Supports a wide range of file formats for exchanging data with other applications, including CAD systems and analysis tools. - **Copy-Paste from Other Applications**: ...
我的第一个服务器这是具有JWT身份验证的简单... - JWT stands for JSON Web Token- JWT is a means of exchanging information between two parties- Digitally signed- Structure of a JWT: {Base64 encoded Header}