User's collector

Внимание!   Данная опция будет доступна только после того, как вы авторизуетесь.
   запомнить меня 

Хорошие люди попросили разместить объявление, что я и сделал. :)

В компанию «Датэк» для работы над проектом «COMDI» требуются хорошие программисты:

Flex/Flash программист

  • Хорошее знание ActionScript3, Flex.
  • Опыт разработки полноценных веб-приложений
  • Желателен опыт работы с медиа серверами (FMS, Wowza).

JAVA программист

  • Опыт разработки апплетов, работа с изображениями.
  • Желательно, опыт работы с JNI.
  • Необходимо представление о работе WinAPI, cетевых протоколах, желательно P2P.
  • Придется разрабатывать системы скриншаринга, удаленного управления рабочим столом, работа с веб-камерами, p2p соединения и т.д.

Работа постоянная в современном офисе, в районе ВДНХ. Уровень ЗП – 70,000-100,000.
Резюме присылайте на egor.voronin@gmail.com

Комментариев нет

Теги:

А знаете ли вы, что, начиная с версии 5, в Java появилась такая интересная «фишка», как импорт статических членов класса? Выглядит это следующим образом. Допустим, в нашем классе в нескольких местах используется метод Math.random(). Если поместить в начало класса следующий импорт:

JAVA:
  1. import static Math.random;

то мы можем в любом месте этого класса вызывать метод при помощи более короткой записи:

JAVA:
  1. double val = random();

Можно импортировать все статические члены класса, указав вместо названия конкретного поля или метода символ *:

JAVA:
  1. import static Math.*;

В Groovy импорт статических членов также поддерживается, но в более продвинутой форме — кроме указания имени импортируемого члена класса, можно указывать еще и псевдоним (англ. alias), через который этот член будет доступен в коде:

GROOVY:
  1. import static Math.random as rand

Таким образом, мы создали псевдоним rand и теперь можем через него производить вызов статического метода Math.random:

GROOVY:
  1. double value = rand()

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

GROOVY:
  1. import groovy.lang.ExpandoMetaClass as EMC
  2. // ...
  3. def metaClass = new EMC(Integer)

В ActionScript 3 подобного функционала пока нет, но если он появится в будущих версиях, то этот язык станет чуточку более удобным.

7 комментариев

Теги:

Наверняка ведь многие задавались вопросом: «Почему бы не использовать вместо Одиночки обычный класс со статическими методами и свойствами?». В ActionScript 3 создать Singleton без дополнительных маневров не получится и бывают случаи, когда хочется попросту обойтись без них.

На самом деле есть несколько причин, выступающих за то, чтобы использовать Одиночку:

  1. В ActionScript 3 статические методы и свойства не наследуются. Т. е. если вы реализовали какой-либо функционал в виде статических членов класса, то он не будет передан по наследству подклассам класса и вам придется заново определять этот функционал в каждом из подклассов.
  2. В дальнейшем ходе развития кода вашего приложения вы можете пересмотреть политику взаимодействия объектов в нем. И вам может понадобиться уже несколько экземпляров вашего класса, каждый из которых будет хранить собственные значения свойств, обладая при этом схожим с другими экземплярами функционалом. В случае использования Одиночки это делается без особого труда — достаточно переделать статический метод getInstance так, чтобы он каждый раз возвращал новый объект класса. Есть даже специальное название для паттерна, обладающего с Singleton схожей структурой, но позволяющего создавать несколько экземпляров классов и вести их учет — Multiton. В случае же использования класса со статическими членами это сделать уже довольно сложно: пришлось бы создавать полностью одинаковые классы-дубликаты нашего класса, что само по себе является просто ужасным примером дизайна приложения.
  3. Значения статическим членам класса будут присвоены во время инициализации самого класса. На практике это означает, что, как только дойдет очередь до инициализации класса, AVM или JVM присвоит статическим свойствам этого класса необходимые значения, и с этого момента они будут постоянно висеть в памяти, занимая и растрачивая попусту ресурсы компьютера. Это может быть особенно заметно, если класс хранит достаточно увесистые объекты типа изображений, звуков или видео. Кроме того потребуется больше времени и на запуск приложения. В отличие от этого варианта, вы можете разработать ваш Singleton таким образом, чтобы он поддерживал «ленивую» инициализацию. «Ленивой» называется создания экземпляра класса и присваивание значений его свойствам только тогда, когда это необходимо на самом деле, т.е. во время первого вызова getInstance.
  4. Использование объектов — более легкий вариант для понимания и отладки. Использование статических членов класса, которые не являются частью какого-то простого объекта, а принадлежат к самому классу, означает, что ваш код не создается в определенной точке вашего приложения. В результате этого могут возникать ошибки, которые довольно сложно выявить. Главным образом это проявляется, если ваш класс должен содержать ссылки на другие объекты, которые попросту еще не будут доступны во время инициализации свойств класса.

И так, в ситуациях, когда Singleton имеет преимущества перед использованием статических членов класса, мы разобрались. Но когда же будет полезно использование обычного класса со статическими свойствами и методами?

При создании классов утилит, т. е. классов представляющих собой библиотеки связанных друг с другом статических методов и статических полей, предназначенных для обработки простых значений или выполнения простых задач, не требующих взаимодействия с другими объектами. Примерами таких классов являются Math в ActionScript 3 или java.util.Arrays в Java. Создание экземпляров таких классов являлось бы абсурдным. Так же, маловероятно, что когда-нибудь потребуется наследоваться от этих классов. И, как правило, классы утилит не содержат большого количества полей и методов, чтобы это заметно сказывалось на времени запуска приложения. Поэтому в данном случае предпочтительнее использование класса со статическими членами вместо Одиночки.

Однако не забывайте снабжать утилитный класс конструктором, выбрасывающим ошибку при попытке создания экземпляра класса, чтобы сделать невозможным инстанцирование объектов этого класса. В ActionScript 3 это делается так:

Actionscript:
  1. package
  2. {
  3.     public class Foo
  4.     {
  5.         public function Foo()
  6.         {
  7.            throw new Error("You can't create instance of Foo. All its methods and properties are static");
  8.         }
  9.     }
  10. }

В ActionScript 2 или Java используйте простой приватный конструктор.

P.S.: Обязательно прочтите статью «Работа с сookies в as3 приложениях» от Алексея «Vooparker» Аникутина, в которой как раз и приводится пример небольшого, но очень полезного утилитного класса.

См. так же:

10 комментариев

Теги:

Оригинал статьи: Getting Started With Red5 Server
Автор: Milan Toth
Перевод: Алексей «Vooparker» Аникутин

Часть первая — Установка среды

В целом это статья в большей степени посвящена Java, чем ActionScript, однако если ты flash-flex разработчик, то рано или поздно тебе потребуется столкнуться с разработкой проектов под сервер Red5.
Прежде всего, нам потребуется установить сам сервер Red5 версии 0.6 (для успешного завершения этого урока автор предлагает использовать именно эту версию, так изменения между релизами могут быть весьма значительны, со всеми вытекающими отсюда последствиями. Прим. переводчика — на версии 0.6.1 полет нормальный).

Нам также в этом уроке потребуется Eclipse, если у тебя его еще до сих пор нет, тогда тебе сюда. Устанавливаем и Eclipse и Red5 в «штатном» режиме. Так же было бы не плохо обзавестись XMLBuddy), плагином к Eclipse, он будет нам полезен для редактирования конфигурационных xml-файлов. Устанавливается просто — копированием в папку [Eclipse_HOME]/plugings. Так же там потребуется Adobe Flex Builder 2, автор предлагает установить его в качестве плагина к существующей установке Eclipse, поскольку очень удобно разрабатывать и серверную и клиентскую часть не переключаясь с одной среды разработки на другую.

Если у вас не установлено ни JRE, ни JDK вам придется их установить. Взять их можно здесь. Вам также придется разобраться с java CLASSPATH, за подробностями можете обращаться на страницы Sun.

И так настало время ознакомиться с корневой директорией установки Red5: red5.jar содержит необходимые классы для разработки под red5, в директории webapps располагаются наши приложения. Jetty servlet container ищет приложения в этой директории по конфигурационным xml-файлам, расположенных в папках WEB-INF.

Мы можем создать наше red5 приложение многими способами. Мы можем использовать Apache Ant для компиляции нашего приложения, основанного на red5/build.xml, но этот способ сложнее. Мы воспользуемся Eclipse’ом для написания и компиляции нашего приложения, после чего запустим Red5.

Запускаем Eclipse, кликаем по пункту меню File → New Project, выбираем Java Project, в качестве названия вводим Red5FirstApp и нажимаем Finish.

В виде Package Explorer появился только что созданный проект с библиотекой классов установленной в системе JRE. Кликаем правой кнопкой по проекту, New → Folder, называем директорию WEB-INF. В только что созданной WEB-INF создаем папки classes и src.

Теперь скажем Eclipse, что в качестве корневой директории для наших исходных файлов будет использовать папка WEB-INF/src, для этого правый клик на ней Build Path → Use as Source Folder.

Для хранения скомпилированных классов мы должны установить директорию WEB-INF/classes. Для этого кликаем пункт Project → Properties. Выбираем Java Build Path → вкладка Source. В самом низу находим Default Output Folder, нажимаем Choose и выбираем WEB-INF/classes.

И так мы почти готовы, осталось последнее — расположить конфигурационный файлы. Открываем папку [red5_HOME]/doc/templates/myapp/WEB-INF и копируем все 4 файла в [Eclipse_Workspace]/Red5FirstApp/WEB-INF. После чего переключаемся в Eclipse, правым кликом на проекте и выбираем Refresh, после чего скопированные файлы появятся в проекте.

Часть вторая – Написание простого приложения

И так все готово для того, чтобы приступить к написанию нового приложения. Правый клик на WEB-INF/src, выбираем New → Class, в качестве пакета указываем com.milgra, в качестве имени класса — Application, после чего нажимаем Finish. Созданный нами класс появится в редакторе.

Этот класс и будет основным классом нашего приложения, однако для этого необходимо чтобы он наследовался от класса ApplicationAdapter, входящего в библиотеку red5. Так что для начала нам потребуется добавиться эту библиотеку к проекту. Кликаем пункт Project → Properties, выбираем Java Build Path, затем вкладку Libraries и нажимаем Add External JARs, находим red5.jar директории установки Red5. Теперь Eclipse сможет скомпилировать наше приложение и подсказывать нам.

Сначала создадим два метода appStart и appStop:

JAVA:
  1. package com.milgra;
  2. import org.red5.server.adapter.ApplicationAdapter;
  3. public class Application extends ApplicationAdapter
  4. {
  5.     public boolean appStart ( )
  6.     {
  7.  
  8.     }
  9.     public void appStop ( )
  10.     {
  11.  
  12.     }
  13. }

Было бы не плохо отследить клиентское соединение, для этого нам потребуется импортировать новый класс:

JAVA:
  1. import org.red5.server.api.IConnection;

Теперь мы можем добавить еще два метода:

JAVA:
  1. public boolean appConnect( IConnection conn , Object[] params )
  2. {
  3.     return true;
  4. }
  5.  
  6. public void appDisconnect( IConnection conn , Object[] params )
  7. {
  8.  
  9. }

Для отладки нашего приложения мы воспользуемся логгингом, мы создадим логгер, который будет выводить сообщения в стандартный аутпут. Так что давайте импортируем классы Log и LogFactory:

JAVA:
  1. import org.apache.commons.logging.Log;
  2. import org.apache.commons.logging.LogFactory;

Eclipse укажет на ошибки в этих строках, все потому что мы не импортировали соответствующую библиотеку. Так что давайте сделаем это. Кликаем Project → Properties. Раздел Java Build Path, вкладка Libraries. Нажимаем Add External JARs и выбираем commons-logging-1.1.jar в директории [red5_HOME]/lib и нажимаем OK.

Дополним наш класс:

JAVA:
  1. private static final Log log = LogFactory.getLog( Application.class );
  2.  
  3. public boolean appStart ( )
  4. {
  5.     log.info( "Red5First.appStart" );
  6.     return true;
  7. }
  8.  
  9. public void appStop ( )
  10. {
  11.     log.info( "Red5First.appStop" );
  12. }
  13.  
  14. public boolean appConnect( IConnection conn , Object[] params )
  15. {
  16.     log.info( "Red5First.appConnect " + conn.getClient().getId() );
  17.     return true;
  18. }
  19.  
  20. public void appDisconnect( IConnection conn , Object[] params )
  21. {
  22.     log.info( "Red5First.appDisconnect " + conn.getClient().getId() );
  23. }

Так как наша задача сделать простой пример, то и логика приложения будет такой же простой, если мы передаем true серверу при соединении, мы позволяем клиентскому приложению подключиться, в противном случае, сервер отклонит попытку соединения.

JAVA:
  1. private static final Log log = LogFactory.getLog( Application.class );
  2.  
  3. public boolean appStart ( )
  4. {
  5.     log.info( "Red5First.appStart" );
  6.     return true;
  7. }
  8.  
  9. public void appStop ( )
  10. {
  11.     log.info( "Red5First.appStop" );
  12. }
  13.  
  14. public boolean appConnect( IConnection conn , Object[] params )
  15. {
  16.     log.info( "Red5First.appConnect " + conn.getClient().getId() );
  17.  
  18.     boolean accept = (Boolean)params[0];
  19.  
  20.     if ( !accept ) rejectClient( "you passed false..." );
  21.  
  22.     return true;
  23. }
  24.  
  25. public void appDisconnect( IConnection conn , Object[] params )
  26. {
  27.     log.info( "Red5First.appDisconnect " + conn.getClient().getId() );
  28. }<

Итоговый код должен выглядеть так:

JAVA:
  1. package com.milgra;
  2.  
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5.  
  6. import org.red5.server.api.IConnection;
  7. import org.red5.server.adapter.ApplicationAdapter;
  8.  
  9. public class Application extends ApplicationAdapter
  10. {
  11.     private static final Log log = LogFactory.getLog( Application.class );
  12.  
  13.     public boolean appStart ( )
  14.     {
  15.         log.info( "Red5First.appStart" );
  16.         return true;
  17.     }
  18.  
  19.     public void appStop ( )
  20.     {
  21.         log.info( "Red5First.appStop" );
  22.     }
  23.  
  24.     public boolean appConnect( IConnection conn , Object[] params )
  25.     {
  26.         log.info( "Red5First.appConnect " + conn.getClient().getId() );
  27.  
  28.         boolean accept = (Boolean)params[0];
  29.  
  30.         if ( !accept ) rejectClient( "you passed false..." );
  31.  
  32.         return true;
  33.     }
  34.  
  35.     public void appDisconnect( IConnection conn , Object[] params )
  36.     {
  37.         log.info( "Red5First.appDisconnect " + conn.getClient().getId() );
  38.     }
  39. }

И так мы полностью разобрались с Java. Все что нам осталось это разобраться с конфигурационными файлами. Так что, все наше вниманием теперь четырем файлам в папке WEB-INF.

  • log4j.properties:
    параметры логгинга нашего приложения;
  • red5-web.properties:
    этот файл инклудится red5-web.xml, постоянные параметры могут располагаются здесь. webapp.contextPath хранит в себе путь к нашему приложению (не стоит писать в начале пути webapps), установим значение этого параметра на firstapp:

    CODE:
    1. webapp.contextPath=/firstapp
    2. webapp.virtualHosts=localhost, 127.0.0.1

    теперь файл можно сохранить.

  • red5-web.xml:
    Spring загружает и конфигурирует наше приложение основываясь на этом файле. Bean обработчики также могут располагаться здесь.
    В этом файле находим web.handler и в значение атрибута class вписываем путь до нашего приложения:

    XML:
    1. <bean id="web.handler"
    2.         class="com.milgra.Application"
    3.         singleton="true" />

    Также можете удалить myhandler.service, так в нашем случае нам он не потребуется.

  • web.xml:
    Это файл будет прочитан Jetty первым. Переименуйте приложение здесь в firstapp, и удалите две секции в которых описывается gateway.

    XML:
    1. <context -param>
    2.     <param -name>webAppRootKey</param>
    3.     <param -value>/firstapp</param>
    4. </context>

Ну что ж теперь можно собрать наш проект. Project → Build Automatically, теперь Eclipse будет перекомпиливать проект после каждого изменения, что не может не радовать.

Последний шаг — установка приложения на сервер. Создайте новую директорию в папке red5/webapps и назовите ее firstapp (это имя мы указывали в файле red5-web.properties). И скопируйте в эту директорию WEB-INF из [Eclipse_Workspace]/Red5FirstApp. Теперь запускаем сервер red5 и наше приложение готово.

Часть третья — Создание клиентского flash-приложения

И так серверная часть готова, настало время опробовать ее в работе.

И так переключаемся во Flex Builder, создаем новый Actionscript project и называем его Red5FirstClient:

Actionscript:
  1. package
  2. {
  3.  
  4.     import flash.net.NetConnection;
  5.     import flash.net.ObjectEncoding;
  6.     import flash.events.NetStatusEvent;
  7.     import flash.display.Sprite;
  8.  
  9.     public class Red5FirstClient extends Sprite
  10.     {
  11.  
  12.         private var nc:NetConnection;
  13.  
  14.         public function Red5FirstClient()
  15.         {
  16.  
  17.             // new netconnection
  18.  
  19.             nc = new NetConnection( );
  20.  
  21.             // set encoding to old amf
  22.  
  23.             nc.objectEncoding = ObjectEncoding.AMF0;
  24.  
  25.             // netstatus event listening
  26.  
  27.             nc.addEventListener( NetStatusEvent.NET_STATUS , netStatus );
  28.  
  29.             // connect to red5, passing false as parameter
  30.  
  31.             nc.connect( "rtmp://localhost/firstapp" , false );
  32.  
  33.         }
  34.  
  35.         private function netStatus ( event:NetStatusEvent ):void
  36.         {
  37.  
  38.             trace( event.info.code );
  39.  
  40.             if ( event.info.code == "NetConnection.Connect.Rejected" )
  41.             {
  42.  
  43.                 // trace reject message
  44.  
  45.                 trace( event.info.application );
  46.  
  47.             }
  48.  
  49.         }
  50.  
  51.     }
  52.  
  53. }

Теперь кликаем Run → Debug. Так как в качестве параметра при соединении мы передали false, red5-приложение отклонит попытку, а в логе появиться строка:

[INFO] 87028 pool-2-thread-8:( com.milgra.Application.appConnect ) Red5First.appConnect 1

Что означает, что наше клиентское приложение подключилось к серверу. Теперь проверим flex-консоль:

CODE:
  1. NetConnection.Connect.Rejected
  2. you passed false . . .
  3. NetConnection.Connect.Closed

Серверное приложение отклонило соединение, а также передало сообщение, то есть оно работает так, как мы и планировали.
Теперь изменим значение параметра передаваемого при соединении на true, и посмотрим что произойдет:

Actionscript:
  1. nc.connect( "rtmp://localhost/firstapp" , true );

в консоле мы увидим:

CODE:
  1. NetConnection.Connect.Success

А это означает, что наше приложение работает! :)

UPD: Файлы к статье "Начало разработки с Red5"

31 комментарий

Теги: