Статьи

Перезарядите свое приложение Flex с помощью ColdFusion Power

Здесь, в SitePoint, есть немало учебников, которые помогут вам понять некоторые из ключевых принципов создания многофункциональных интернет-приложений (RIA) с использованием Flex и AIR. Вы обнаружите, что большинство разработок во Flex будет включать в себя фоновое приложение для взаимодействия с клиентом Flex.

Давайте обсудим некоторые теории и принципы, из которых состоит приложение Flex, а затем применим эти принципы на практике с помощью приложения ColdFusion. Здесь мы предполагаем, что у вас уже есть опыт разработки ColdFusion.

Обратите внимание, потому что в конце есть тест. Благодаря нашему спонсору, Adobe, первые 100 человек, прошедших тест, получат копию « Начало работы с Flex 3» . Пройди тест!

Понимание архитектуры насыщенного интернет-приложения

С точки зрения высокого уровня, общая системная архитектура веб-приложения обычно состоит из трех уровней.

Нижний уровень состоит из уровня хранения данных, обычно системы реляционных баз данных, такой как Microsoft SQL Server, Oracle или MySQL. Такой уровень обеспечивает модель реляционной таблицы, которую можно использовать для хранения и извлечения данных приложения.

Уровень выше уровня хранения данных называется сервером приложений или промежуточным программным обеспечением. На этой площадке обычно используются технологии Adobe ColdFusion, Java, PHP, Ruby on Rails или .NET. Эти платформы используются для разработки бизнес-логики и логики доступа к данным.

Помимо этого, или, возможно, даже встроенного в промежуточное ПО, мы найдем слой, отвечающий за доставку HTTP — то есть веб-серверы, такие как IIS или Apache. В насыщенных интернет-приложениях архитекторам иногда приходится иметь дело с другими протоколами, кроме HTTP: такие технологии, как Flash Media Server, например, поддерживают протокол потоковой передачи в реальном времени RTMP.

В моем предыдущем уроке я показал, как приложение Flex может взаимодействовать с другими приложениями и данными на стороне клиента. На этот раз мы теперь будем общаться с нашими уровнями бизнеса и данных на стороне сервера.

Как Flex связывается

Flex может получать доступ к удаленным данным в основном тремя различными способами:

  • HTTP-вызовы плоских файлов, XML-файлов или динамических URL-адресов, которые доставляют данные, с которыми может работать Flex
  • SOAP-вызовы веб-сервисов
  • Вызовы удаленных объектов в формате Action Message Format (AMF).

Каждый из этих методов представлен различными классами ActionScript и тегами MXML. Справедливо сказать, что синтаксис тегов MXML, вероятно, проще использовать, если исходить из фона ColdFusion, потому что вы можете использовать синтаксис, аналогичный синтаксису ColdFusion CFML.

HTTPService: получение данных по HTTP

Давайте подумаем о теге mx:HTTPService . Неудивительно, что это служба на основе HTTP, которую мы можем использовать для получения некоторых данных из других мест во время выполнения. В MXML такой сервис будет объявлен так:

 <mx:HTTPService id="dataService"  url="http://www.example.com/xmlfile.xml" /> 

Атрибут id предоставляет ссылку на объект службы. Атрибут url указывает на статический файл XML, который доступен через HTTP, но может также указывать на локальный файл, например:

 <mx:HTTPService id="dataService" url="xmlfile.xml" /> 

В этом случае приложение Flex ожидает найти файл XML по тому же пути, что и сам.

Естественно, что ColdFusion может генерировать для нас какой-то XML. Вот очень простой способ сделать это:

 <cfsavecontent variable="xmlContent"><data>    <result>        <item>Taxes</item>        <amount>2000</amount>    </result>    ...  </data></cfsavecontent>   <cfcontent reset="true" type="text/xml"><cfoutput>#xmlContent#</cfoutput> 

Тег хранит созданный статический или динамический контент в переменной xmlContent . Затем мы используем тег cfcontent для сброса любого вывода, который мы могли создать ранее, и указываем тип содержимого text/xml . Затем мы доставляем содержимое переменной xmlContent с помощью простого тега cfoutput . Вуаля, выходит немного XML.

На следующей странице мы рассмотрим приложение Flex, которое будет использовать этот XML.

Приложение Flex для обслуживания такого вызова службы будет выглядеть следующим образом:

 <?xml version="1.0" encoding="utf-8"?>  <mx:Application  xmlns:mx="http://www.adobe.com/2006/mxml"  layout="horizontal"  creationComplete="cfmFile.send()">     <mx:Script>        <![CDATA[            import mx.controls.Alert;            import mx.rpc.events.ResultEvent;            import mx.rpc.events.FaultEvent;            import mx.collections.ArrayCollection;             [Bindable]            private var budgetData:ArrayCollection = new ArrayCollection();             private function cfmFileRH(e:ResultEvent):void            {                budgetData = e.result.data.result as ArrayCollection;            }             private function cfmFileFH(e:FaultEvent):void            {                mx.controls.Alert.show(e.fault.faultString,"Error when loading XML");            }          ]]>    </mx:Script>     <mx:HTTPService    id="cfmFile"    url="http://example.com/budgetXML.cfm"    result="cfmFileRH(event)"    fault="cfmFileFH(event)"    />     <mx:DataGrid dataProvider="{budgetData}" >    </mx:DataGrid>   </mx:Application> 

Вот что происходит: мы используем mx:HTTPService для получения некоторых данных и сохраняем результат от службы в переменной с именем budgetData . Обработчик события creationComplete для тега отправляет запрос HTTPService при создании приложения. Наконец, объект mx:DataGrid отображает данные в виде таблицы.

Если присмотреться к mx:HTTPService мы увидим, что он включает в себя два атрибута: result и fault . Во Flex любой запрос службы данных обрабатывается асинхронно, что означает, что приложение Flex немедленно передает широковещательное событие, а не ожидает ответа. Все сервисные теги предлагают result атрибутов и fault чтобы иметь дело с любым из этих результатов. В этих атрибутах вы просто указываете имя метода, который вы хотите вызывать всякий раз, когда результат (или ошибка) возвращается после вызова службы.

Практически говоря, экземпляр mx:HTTPService ограничен запросами GET и POST , хотя в принципе могут быть выполнены другие запросы, но они недоступны, если запросы HTTP не маршрутизируются через прокси-сервер, такой как Adobe BlazeDS или LiveCycle Data Services. , Причиной такого ограничения является модель безопасности Flash Player, которая поддерживает только прямые вызовы GET или POST через HTTP. Вот где в игру вступает другая концепция: файл междоменной политики.

Обычно приложение на основе Flash, использующее mx:HTTPService или веб-службу на основе SOAP, может извлекать данные только из службы или файла, хранящегося на том же сервере, что и файл .swf. Чтобы определить, извлекаются ли данные из одного и того же домена, проигрыватель Flash Player сравнивает имена доменов, используемые для файла Flash и удаленного источника данных. Это означает, что приложение, загруженное с http: //localhost/test.swf, не может получить доступ к данным HTTP с http://127.0.0.1/data/xmlfile.xml — даже если они являются одним и тем же сервером. Одним из решений является использование файла междоменной политики с именем crossdomain.xml, размещенного в корневом веб-каталоге сервера, который предназначен для предоставления данных. Вы можете узнать больше о том, как использовать файл междоменной политики, в документации Adobe .

Далее давайте узнаем об отправке параметров запроса во Flex.

Параметры запроса на отправку

Возможно, вам нужно отправить параметры к вашему сервису. Самый простой способ передать параметры — это добавить тег mx:request в качестве вложенного тега службы HTTP. Давайте представим, что нам нужно отправить два параметра, dataMethod и userType , в скрипт ColdFusion. Мы бы использовали элемент mx:request так:

 <mx:HTTPService id="dataService" url="http://example.com/sendDataRequest.cfm" method="POST">   <mx:request>       <dataMethod>getAll</dataMethod>       <userType>administrator</userType>    </mx:request>  </mx:HTTPService> 

Поскольку мы используем метод HTTP POST , все переменные запроса, которые мы здесь создаем, станут переменными ColdFusion в области видимости ColdFusion FORM . Поэтому на стороне ColdFusion мы собираемся использовать FORM.dataMethod а также FORM.userType в шаблоне ColdFusion. Если бы вы выбрали HTTP GET (указав method="GET" ), ваши данные запроса станут переменными URL: в этом случае URL.userType и URL.dataMethod .

До сих пор мы только что рассмотрели возврат XML-данных через HTTP-сервисы из шаблонов ColdFusion. Хотя это очень распространенный способ взаимодействия со службами HTTP и ColdFusion, существуют некоторые другие альтернативные форматы возврата для служб HTTP, которые в некоторых случаях могут быть более подходящими для использования:

  • object : данные ответа являются XML и будут преобразованы в дерево объектов ActionScript ( ArrayCollection , ObjectProxy )
  • Данные xml : response представляют собой XML и будут преобразованы в объект ActionScript типа XMLnode — это устаревший формат, который используется только для совместимости; Лучше избегать его использования.
  • e4x : данные ответа являются XML и будут преобразованы в объект ActionScript XML
  • flashvars : данные ответа представляют собой цепочку пар ключ / значение: name1=value1&'name2=value2 и т. д.
  • text : данные ответа — текст, конверсия не происходит.
  resultFormat="object" - это значение по умолчанию, и зачастую это правильный путь.  Если вы хотите работать с XML вместо ArrayCollections и ObjectProxy , e4x (ECMAScript для XML) является предпочтительным форматом результата - xml использует устаревший набор классов API, который является частью Flex только для совместимости.

Предоставление услуги с ColdFusion

Итак: мы провели большую часть этой статьи, рассказывая о HTTP-сервисах и общей структуре сервиса. Теперь, когда мы понимаем, как они работают, обсуждение веб-сервисов и удаленных объектов становится намного проще.

Давайте возьмем следующий компонент ColdFusion, который предлагает один простой метод echo для внешнего мира, и попробуем встроить клиента Flex, который подключается к этому CFC:

 <cfcomponent>x    <cffunction      name="echo"      returntype="string"      access="remote"      output="false"      hint="I echo whatever I'm being passed">        <cfargument name="input" type="string" required="true">        <cfreturn "Echoing..." & arguments.input>    </cffunction>  </cfcomponent> 

ColdFusion предлагает два способа представления функциональности метода этого компонента вызывающей стороне: в виде веб-службы на основе SOAP или в качестве удаленного объекта. Давайте попробуем каждый.

МЫЛО

Начиная с веб-службы SOAP, мы сделали метод echo методом веб-службы, установив атрибут access="remote" в теге cffunction . В то же время этот параметр позволит нам вызывать метод как удаленный объект. Мы хотели бы получить данные в формате WSDL, что можно сделать, просто добавив ?WSDL в конец URL.

Чтобы получить этот WSDL во Flex, мы начнем с использования mx:WebService , структура которого во многом аналогична mx:HTTPService :

 <mx:WebService  id="dataWS"  wsdl="http://example.com/service.cfc?WSDL"  result="onDataServiceResult(event)"  fault="onDataServiceFault(event)"  /> 

С веб-сервисами вы часто обнаружите, что сервис предлагает несколько методов, и вы предпочитаете указывать метод обработки результата или ошибки для каждой службы. Это возможно при использовании mx:operation :

 <mx:WebService      id="dataWS"      wsdl="http://example.com/service.cfc?WSDL"      fault="onDataServiceFault(event)"    >        <mx:operation name="echo" result="onResultEcho(event)" />    </mx:WebService> 

Предоставление параметров для вызовов веб-службы работает аналогично предоставлению параметров для вызовов службы HTTP - через mx:request - но также может быть выполнено с использованием синтаксиса, знакомого разработчикам из языков, таких как Java или C ++:

 dataWS.echo("Hello") 
Формат сообщения действия

Теперь давайте попробуем это с форматом сообщения действия (AMF). AMF - это протокол, который существует довольно давно, и спецификация AMF3 была публично выпущена Adobe в декабре 2007 года. На стороне сервера вам понадобится служба с поддержкой AMF3 - к счастью, как разработчик ColdFusion, вы готовы предоставить этот вид услуг прямо из коробки.

Во Flex мы можем использовать тег mx:RemoteObject для взаимодействия с удаленными объектами:

 <mx:RemoteObject  id="dataRS"  destination="ColdFusion"  source="example.service">    <mx:method      name="echo"      result="onResultEcho(event)"      fault="onFaultEcho(event)"  />  </mx:RemoteObject> 

Сравнивая этот код с эквивалентным объявлением веб-службы во Flex, мы обнаруживаем несколько небольших различий: мы имеем дело с местом назначения с именем «ColdFusion», и mx:operation поменялась на mx:method .

Когда кто-то сначала настраивает проект Flex для ColdFusion в Flex Builder, мастер установки задаст несколько вопросов, касающихся расположения сервера ColdFusion, его порта, URL-адреса и корневого контекста. Затем предоставленная информация будет использоваться во время компиляции приложения Flex, чтобы предоставить Flex сведения о URL-адресе AMF. Это работает плавно и легко для простых типов данных, таких как строки или логические значения, или даже для встроенных типов ColdFusion, таких как массивы и структуры.

Возможно, вы даже захотите работать с целыми объектами из бизнес-домена вашего приложения и передавать их туда и обратно. Существует шаблон проектирования, называемый объектом передачи данных или объектом значения, который описывает такой процесс, и его довольно просто использовать с компонентами ColdFusion. Ваша конфигурация сервиса во Flex в основном останется прежней, но вместо отправки или ожидания простых типов от вызова удаленного объекта это будет объект домена: объект, представляющий покупателя, корзину, сотрудника или все, что вы планируете иметь дело с. Чтобы позволить Flex иметь дело с такими сложными типами объектов, ColdFusion также должен знать о них, и в ColdFusion должен быть эквивалентный компонент. Вот CFC, который описывает пользователя:

 <cfcomponent displayname="User" output="false">   <cfproperty name="user_id" type="numeric" />   <cfproperty name="user_name" type="string" />    <cffunction name="init" access="public" returntype="example.User" output="false">      <cfargument name="user_id" type="numeric" required="false"  />      <cfargument name="user_name" type="string" required="false"  />       <cfset this['user_id'] = arguments.user_id />      <cfset this['user_name'] = arguments.user_name />       <cfreturn this />   </cffunction>  </cfcomponent>  

В следующем минимальном классе ActionScript 3 мы также опишем, что должен содержать объект User:

 [Bindable]  [RemoteClass(alias="example.User")]  public class User  {        public var user_id:int=0;        public var user_name:String="";  } 

Тег метаданных [Bindable] позволяет использовать пользователя в привязках данных Flex. [RemoteClass(alias="example.User")] сопоставляет тип CFC example.User на стороне сервера с классом User здесь в ActionScript.

Что теперь?

Куда мы отправимся отсюда? Если вы используете только ColdFusion, я предполагаю, что вам будет проще использовать RemoteObjects для подобных проектов. Если у вас смешанная среда, состоящая из нескольких технологий, возможно, стоит поискать веб-службы и вызовы службы HTTP для загрузки XML. В любом случае, вы теперь готовы справиться с любой ситуацией: время повеселиться!

Думаешь, ты готов нанести удар ColdFusion? Почему бы не проверить свои новые знания с помощью нашего теста - всего пять простых вопросов, и все ответы были прямо здесь, в этой статье. Первые 100 человек, принявших участие в нашей викторине, получат экземпляр « Getting Started with Flex», доставленный прямо к вашей двери абсолютно бесплатно. Хватай свою!