Создание сайтов - статьи

Возможности интеграции со средами разработки


В качестве демонстрации того, насколько просто создать такое приложение с использованием современных средств разработки, приведем пример, в котором создадим веб-сервис в среде DOT.NET и Java-клиент, вызывающий этот веб-сервис (для демонстрации гетерогенных возможностей технологии).

На практике подобная задача встречается довольно часто. Так что рассмотрим ситуацию из реальной жизни. Система учета супермаркета использовала в качестве базы данных MSSQL-сервер. Таким образом, серверная сторона была привязана к Win2k. Дабы сэкономить на лицензиях Win2k, для торговых терминалов решено было создать рабочее место оператора с использованием UNIX-машин. Для реализации проекта был создан свой протокол с использованием Berkley Sockets. Его создание и отладка отняла значительную часть то общего времени реализации проекта, которое в результате составило примерно полгода! Если бы разработчики использовали веб-сервисы, время разработки значительно сократилось бы.

Приступим непосредственно к созданию нашего примера. В начале создадим проект сервиса. Для этой цели я использовал VS7.1. Запускаем его и создаем новый проект C# на основе шаблона Web Service. При этом в IIS будет создан виртуальный каталог (на диске в соответствие ему ставится реальный каталог), в котором будут размещены файлы проекта.

Рис. 1. Создаем Web Service в среде разработки Visual Studio 7.1

Интерес для нас представляют три файла:

  • *.asmx — файл в формате XML, точнее WSDL (это язык, созданный на базе XML; можно также встретить определение, что WSDL — это XML-схема, оно тоже верно) специально для описания методов, экспонированных сервисом. IIS на лету преобразует WSDL в HTML-представление для отображения в браузере пользователя. Этот файл представляет информацию для description service. Для каждого сервиса (службы) существует свой файл описания;
  • *.disco — файл в формате XML, предназначенный для просмотра (listing) всех существующих веб-служб по указанному адресу: discovery service. Посредством этих двух файлов и IIS пользователь, вооруженный браузером, может найти исчерпывающую информацию об инсталлированных веб-сервисах;
  • *.asmx.cs — файл, ответственный за реализацию методов сервиса.


Переименуйте файл сервиса и класс службы, для того чтобы они несли определенную смысловую нагрузку. Для тестового приложения я выбрал имя файла AccountState.asmx, а для класса службы — AccountState, поскольку наше тестовое приложение будет отображать состояние некоего счета в банке.

Существует распространенное заблуждение, что веб-сервис представляет сущность без состояния. Это не совсем так, мы вполне можем хранить промежуточные данные в статических переменных класса или в переменных приложения. Эти данные будут оставаться живыми вплоть до перегрузки веб-сервера. Верно то, что при каждом новом запросе создается новый экземпляр класса веб-службы. После закрытия клиентом соединения с сервером экземпляр класса будет разрушен — при этом все нестатические члены класса должны быть сохранены в базу данных или посредством serializing. Точно так же они должны быть загружены при новом запросе. Если мы хотим оптимизировать работу сервера, избежав многочисленных обращений к диску или базе данных, оптимальным решением будет сохранение результатов в статической коллекции объектов и сохранение той в хранилище данных через некоторые промежутки времени. Из кода, сгенерированного wizard, несложно догадаться, что место для инициализации — это конструктор класса. Когда нам надо освободить ресурсы, то делать мы следует в методе Dispose().

Код методов нашего веб-сервиса выглядит так:

[WebMethod]
 public string GetBankName()
 {
   return "Baby Bank";
 }
 [WebMethod]
 public void Deposit(int ammount)
 {
   state += ammount;
 }
 [WebMethod]
 public int GetState()
 {
   return state;
 }


 [WebMethod]
 public int Withdraw(int ammount)
 {
   state -= ammount;
   if (state < 0)
   {
     state = 0;
     return state;
   }
   else
   {
     return ammount;
   }


 }




Не забудьте определить переменную state как static (полный код этого примера вы сможете найти на КП-диске).

При вызове сервиса в Internet Explorer мы сможем прочитать пару "запрос-ответ" в формате SOAP. Для примера приведем текст запроса и ответа для функции int GetState() будет выглядеть следующим образом:



Если сравнить формат SOAP с ранее приведенным фрагментом в формате XML-RPC, сразу видно, что при наличии большого количества сложных объектов размер строки XML-RPC будет гораздо меньшим.

Возможность тестировать методы прямо из Internet Explorer делает разработку сервисов еще более простым занятием. Внизу приведены рисунки, отображающие некоторые экраны в процессе тестирования.



Рис. 2. Мы можем просмотреть все методы web службы прямо в Internet Explorer



Рис. 3. Есть возможность вызвать любой метод web службы



Рис. 4. Результат вызова службы в Internet Explorer представлен виде XML

Протестировав наш сервис в Internet Explorer, напишем небольшой консольный клиент, проверяющий его работу.

Код простейшего клиента будет выглядеть так:

[STAThread]
static voidMain(string[] args)
{
  try
  {
    AccountClient.AccountState.AccountState ac
      = new AccountClient.AccountState.AccountState();
    Console.WriteLine("Try to invoke service from URL : " +  ac.Url);
    Console.WriteLine("Bank name : " + ac.GetBankName());
    Console.WriteLine("Accaunt initial state : " + ac.GetState());
    ac.Deposit(10);
    ac.Withdraw(5);
    Console.WriteLine("After Operations accaunt state : " +     ac.GetState());
    ac.Dispose();
    Console.WriteLine("Press key 'Enter' to complete program execution");
    Console.ReadLine();
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);


  }
}


При этом необходимо создать в проекте веб-ссылку, для того чтобы Visual Studio мог сгенерировать промежуточную proxy-сборку. Таким образом, среда разработки берет всю черновую работу на себя, нам остается только создать экземпляр класса и вызвать его методы.

Чтобы создать веб-ссылку, щелкните по контекстному меню на дереве проекта нашего клиента и выберите пункт add web reference. Появится интуитивный дружественный wizard. На рисунке показано его финальное диалоговое окно, где название ссылки изменено с localhost на AccountState.



Рис. 5. Окно визарда, создающего proxy-сборку

Если заглянуть внутрь папки проекта [имя проекта]\Web References, мы обнаружим исходный код нашего proxy-класса. Благодаря применению  атрибутов он достаточно компактен. Стартуйте клиент на выполнение и убедитесь, что все работает.



Рис. 6. Клиент DOT.NET, опрашивающий веб-службу

Если вы запустите его несколько раз, то обнаружите, что данные, хранящиеся в статической переменной state, не будут уничтожены. Но если пересобрать проект, что приведет к перезагрузке приложения в IIS, эти данные все же исчезнут. Поэтому вам в любом случае необходимо позаботиться об их сохранении. Глобальные данные можно сохранять при помощи класса Application.

Первая часть проекта завершена, создадим теперь аналогичный консольный проект Java при помощи среды разработки JBuilder X. Создайте проект, после чего добавьте объект Web Services Designer из меню New. На следующей вкладке визарда установите параметры, как это показано на рисунке 7.



Рис. 7. Настраиваем объект Web Services Designer в среде разработки JBuilder X

После этого в дереве проекта выберите  Web Services Designer > Import WSDL > From URL. Из контекстного меню выберите пункт Add. Будет добавлен новый сервис. Вставьте URL нашего сервиса с постфиксом ?WSDL. Все остальное визард сделает сам — по удобству и интуитивности он ничем не уступает своему аналогу из Visual Studio.

На рисунке ниже показано окно визарда с URL.





Рис. 8. Окно Web Services Designer с импортированным объектом веб-сервиса в среде разработки JBuilder X

Все установки на вкладках оставьте по умолчанию (я изменил только имя пакета для proxy-классов и имя самого сервиса). Соберите проект, в пакете со введенным вами именем возникнут сгенерированные классы. Добавьте новый класс с методом main() и вставьте туда следующий код:

 try
  {
   // here we will invoke our soup method :
   long time1 = System.currentTimeMillis();
   AccountStateSoapStub proxy = (org.tempuri.AccountStateSoapStub)
       new org.tempuri.AccountStateLocator().getAccountStateSoap(new URL(" /Account/AccountState.asmx"));
   if (proxy != null)
   {
     proxy.setTimeout(60000);
     // operations:


     proxy.getBankName();
     System.out.println("Bank name : " + proxy.getBankName());
     System.out.println("Accaunt initial state : " + proxy.getState());
     proxy.deposit(10);
     proxy.withdraw(5);
     System.out.println("After Operations accaunt state : " +  proxy.getState());
     System.out.println("Name : " + proxy.getName());
     proxy.setName("Oleg");
     System.out.println("Name : " + proxy.getName());
     long time2 = System.currentTimeMillis();
     long delta = time2 - time1;
     System.out.println("Request take : " + Long.toString(delta) + " millisecond");
     System.out.println("Press key 'Enter' to complete program execution");
     System.in.read();
   }
 }
 catch (Exception ex)
 {
   ex.printStackTrace();
 }


Следует отметить, что JBuilder использует Apache Axis — самый известный пакет для работы с SOAP. Существуют другие реализации этого протокола — как платные, так и free. Не исключено, они более оптимальны — но если вы остановитесь на одной из них, то почти наверняка потеряете интеграцию с вашей средой разработки. А это означает снижение производительности вашего труда.


Содержание раздела