Любой компании. Ведь сегодня невозможно себе представить выполнение каких бы то ни было работ без компьютеров. С их помощью готовятся доклады и накладные, отчеты и многие другие документы, необходимые для осуществления деятельности компании. А помочь перевести электронный вид всех имеющихся в памяти компьютера документов в бумажный формат позволяет специальная периферийная техника, которой и является офисный принтер.

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

С чего начать?

В настоящее время производители предлагают огромный ассортимент периферийных устройств к компьютеру. Причем дать конкретные рекомендации о том, каким должен быть офисный принтер, и какая модель явится самым оптимальным вариантом для работы, невозможно. Ведь не существует устройства, способного распечатывать красивые фотографии, выдавать стопки цветного и монохромного текста, быть простым в обслуживании и при этом иметь низкую цену. Каждая модель принтера предназначена для решения своего, как правило, неширокого спектра задач. И для максимально эффективного выполнения работы в офисе потребуется довольно серьезно подойти к выбору подходящего периферийного устройства. Первым шагом для этого явится определение той области, в которой ему предстоит работать. Например, это может быть распечатка большого количества текстовых страниц, прайс-листов и буклетов.

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

Расходные материалы

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

Формат документов

Выбирая офисный принтер необходимо также четко представлять, какие по своим размерам тексты или картинки на нем придется распечатывать. Самым распространенным на сегодняшний день является формат А4.

Он соответствует размеру листа бумаги 297х210 мм. В основном именно такие принтеры предлагаются сегодня на рынке периферийной техники. Однако порой в процессе работы требуется распечатка изображений на бумаге формата А3. Он в 2 раза больше, чем описанный выше А4. В этом случае понадобится большой офисный принтер. Как правило, цена на такие модели намного превышает те, которые делают распечатки в объеме стандартных форматов.

Существуют также принтеры, позволяющие распечатать изображения большего, чем А3 размера. Это профессиональная техника, которая носит название плоттеров.

Исследования компьютеров

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

Стоит иметь в виду, что разработанный еще в первых компьютерах параллельный интерфейс, который использует протокол Centronics, уже практически не встречается. Современные принтеры, как правило, обладают последовательными портами USB 1.1, а также 2.0. может быть установлен только для того, чтобы обеспечить совместимость печатающего устройства с устаревшими моделями компьютеров. Многие бюджетные принтеры способны распечатывать документы только из операционной системы Windows. Если же для нужд офиса требуется работать с DOS или Linux, то нужно внимательно прочесть спецификацию выбранной модели. В этом документе обязательно будет указана та операционная система, которая поддерживается принтером.

Существующие стереотипы

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

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

Лазерным принтером можно осуществлять печать на конвертах и наклейках, у которых нет глянцевого покрытия. Также при выборе этого периферийного устройства к компьютеру стоит обратить внимание на указанную в спецификации максимальную и рекомендуемую нагрузку. Для офисного пользования не стоит приобретать принтеры, обладающие начальным уровнем. Ведь они рассчитаны на малый месячный объем печати. При превышении установленной производителем нормы велика вероятность преждевременного износа фотобарабана и выход из строя механической части аппарата. Каковы достоинства лазерных принтеров? Остановимся на них подробнее.

Время выхода первой страницы

Чем привлекателен данный тип периферийного устройства? В большинстве своем это хорошие офисные принтеры, обладающие высокой скоростью печати, порой доходящей до 50 страниц текста в минуту. Еще один немаловажный параметр подобных устройств - время выхода самой первой страницы. Ведь в связи со своими технологическими особенностями лазерные принтеры не могут сразу выдавать нужные документы. После их включения должно пройти определенное время, в течение которого происходит разогревание элемента, который закрепляет тонер. Производителем применяются самые различные разработки, которые способствуют уменьшению этого времени. Тем не менее и на сегодняшний день оно находится в пределах от 9 до 15 секунд.

Оперативная память

Лазерный принтер производит постраничную печать. Но чтобы на листе бумаги появился текст, пользователю необходимо получить о нем полную информацию. С этой целью лазерные принтеры оснащаются Для распечатки текстов ее объема в 8 Мб становится вполне достаточно. В случае работы с графикой память должна быть несколько большей.

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

Для небольших объемов

Весьма популярными являются офисные принтеры Xerox. Например, для небольших объемов рабочим группам может быть приобретен аппарат Phaser 6100. Это модель цветного МФУ, с которой начинается ступенька лазерных принтеров подобного типа у компании "Ксерокс".

На таком устройстве можно распечатывать черно-белые документы со скоростью 20 страниц в минуту. производится в 4 раза медленнее.

Это офисные принтеры, у которых присутствует возможность двусторонней печати. Их процессор обладает тактовой частотой 120 МГц, а также снабжен оперативной памятью в объеме 64 Мб. Все это позволяет принтеру очень быстро обрабатывать практически все имеющиеся задания. Кроме распространенного порта USB 2.0 это периферийное устройство имеет

Для небольших компаний

Малым фирмам может быть порекомендована новая модель монохромного принтера Xerox Phaser 3500. Прибор обладает достаточно высоким уровнем технических характеристик, которые соразмерны его ценовой категории. Скорость печати таких устройств составляет 33 страницы за одну минуту. При этом рассчитанная производителем максимальная месячная нагрузка равна 100 тыс. страниц.

При необходимости высокой скорости печати стоит обратить внимание на модель Brother HL-8050N. Выход продукции в этом монохромном лазерном принтере составляет до 35 листов в течение одной минуты.

Ну а если нужен аппарат, который способен печатать в формате АЗ, то стоит обратить внимание на офисный принтер HP Laser Jet 5100DTN. Его можно встретить не только в кабинетах компаний, но и у пользователей автоматизированных систем проектирования, а также у сотрудников настольных издательств. такого принтера составляет 22 страницы в течение одной минуты. При этом отмечается высокое качество получаемых документов. Такой принтер способен работать и как сетевой.

Почти лазерные

Менее распространенным вариантом устройств, предназначенных для печати, являются светодиодные принтеры. В них нет лазерного луча. Он заменен линейкой неподвижных светодиодных элементов, ширина которой равна ширине строки. Достоинством подобных принтеров является отсутствие в их конструкции сложной механики, а также целой системы зеркал, которая служит для управления лучом лазера. Кроме того, такие принтеры практически бесшумны из-за уменьшения в них количества движущихся элементов.

Среди отрицательных моментов можно выделить качество монохромной печати. Она в светодиодных аппаратах все же хуже, чем в лазерных. Что касается цветных МФУ подобного типа, то они являются лидерами в своей области. Эти аппараты обладают высокой скоростью печати, которая по всем своим показателям превышает лазерные модели аналогичного класса.

Самая популярная модель

Наиболее удачным представителем семейства светодиодных аппаратов можно считать OKI С3200. Это замечательный офисный принтер, цена на который сравнительно невысока и составляет около 480 долларов США. Устройство позволяет получать цветные отпечатки в три раза быстрее, чем это делают лазерные аналоги.

Многофункциональные принтеры

Это отдельный класс устройств. Офисные многофункциональные принтеры способны сканировать документы и распечатывать их. К тому же такие аппараты функционируют как факсы. С их помощью производится копирование нужных документов без использования компьютера.

Это большой офисный принтер, основным достоинством которого является более низкая стоимость по сравнению с покупкой факса, принтера и сканера. При этом ему потребуется меньше места, чем при размещении на столе этих трех устройств.

Для средних по численности рабочих групп, которым необходима цветная печать, предлагается модель 4730. Это цветной принтер, который обладает месячной загрузкой в 10 тыс. страниц и скоростью подачи листов до 30 шт. в течение минуты. У него присутствуют функции копирования и сканирования.

Струйные принтеры

Они также используются в качестве офисной техники. В таких принтерах получаемое на бумаге изображение формируется благодаря струям чернил, которые выбрасываются из печатающей головки. Струйные принтеры позволяют получить цветную печать при использовании заправки разных цветов.

Для небольших офисов компания HP предлагает новую модель Office Jet 5610. Это устройство представляет собой качественный принтер и сканер, способный также выполнять функцию факса.

Матричные принтеры

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

Как правило, указанные принтеры выдают монохромную печать. Цвет текста при этом зависит от цвета красящей ленты. Как правило, ее закупают черной. Однако некоторые модели принтеров обладают модулем для цветной печати. Их система управления принимает во внимание не только работу иголок, но и цвет ленты.

Основные характеристики подобных принтеров заключены в низкой скорости и невысоком качестве печати. Но в то же время такие устройства великолепно подходят для работы с непрерывным листом бумаги. Используют их и для печати документов под копирку. Среди достоинств матричных принтеров отмечается их простота конструкции и надежность. К тому же стоимость выдаваемого ими листа текста в десятки раз ниже, чем у лазерных аналогов. К большому сожалению, при своей работе они создают высокий уровень шума, способного отвлечь сотрудников от работы.

Самой популярной линейкой матричных принтеров являются модели от компании Epson. При этом выделяют устройство LX-300. Это самая популярная и доступная модель такого типа, которую выделяют высокая скорость печати, достигающая 337 знаков в течение минуты, надежность и возможность установки блока, предназначенного для выхода цветного текста.

Заголовок топика – это действительно вопрос, т.к. я сам не знаю, что это и впервые попробую поработать с этим в рамках настоящей статьи. Единственное, что могу гарантировать, что код, представленный ниже, будет работать, однако мои фразы будут лишь предположениями и догадками о том, как я сам все это понимаю. Итак, поехали…

Введение

Начать надо с того, для чего создавалась концепция веб-сервисов. К моменту появления этого понятия в мире уже существовали технологии, позволяющие приложениям взаимодействовать на расстоянии, где одна программа могла вызвать какой-нибудь метод в другой программе, которая при этом могла быть запущена на компьютере, расположенном в другом городе или даже стране. Все этого сокращенно называется RPC (Remote Procedure Calling – удаленный вызов процедур). В качестве примеров можно привести технологии CORBA, а для Java – RMI (Remote Method Invoking – удаленный вызов методов). И все вроде в них хорошо, особенно в CORBA, т.к. с ней можно работать на любом языке программирования, но чего-то все же не хватало. Полагаю, что минусом CORBA является то, что она работает через какие-то свои сетевые протоколы вместо простого HTTP, который пролезет через любой firewall. Идея веб-сервиса заключалась в создании такого RPC, который будет засовываться в HTTP пакеты. Так началась разработка стандарта. Какие у этого стандарта базовые понятия:
  1. SOAP . Прежде чем вызвать удаленную процедуру, нужно этот вызов описать в XML файле формата SOAP. SOAP – это просто одна из многочисленных XML разметок, которая используется в веб-сервисах. Все, что мы хотим куда-то отправить через HTTP, сначала превращается в XML описание SOAP, потом засовывается в HTTP пакет и посылается на другой компьютер в сети по TCP/IP.
  2. WSDL . Есть веб-сервис, т.е. программа, методы которой можно удаленно вызывать. Но стандарт требует, чтобы к этой программе прилагалось описание, в котором сказано, что «да, вы не ошиблись – это действительно веб-сервис и можно у него вызвать такие-то такие-то методы». Такое описание представляется еще одним файлом XML, который имеет другой формат, а именно WSDL. Т.е. WSDL – это просто XML файл описания веб-сервиса и больше ничего.
Почему так кратко спросите вы? А по подробней нельзя? Наверное можно, но для этого придется обратиться к таким книгам как Машнин Т. «Web-сервисы Java». Там на протяжении первых 200 страниц идет подробнейшее описание каждого тега стандартов SOAP и WSDL. Стоит ли это делать? На мой взгляд нет, т.к. все это на Java создается автоматически, а вам нужно лишь написать содержимое методов, которые предполагается удалено вызывать. Так вот, в Java появился такой API, как JAX-RPC. Если кто не знает, когда говорят, что в Java есть такой-то API, это означает, что есть пакет с набором классов, которые инкапсулируют рассматриваемую технологию. JAX-RPC долго развивался от версии к версии и в конечном итоге превратился в JAX-WS. WS, очевидно, означает WebService и можно подумать, что это простое переименование RPC в популярное нынче словечко. Это не так, т.к. теперь веб-сервисы отошли от первоначальной задумки и позволяют не просто вызывать удаленные методы, но и просто посылать сообщения-документы в формате SOAP. Зачем это нужно я пока не знаю, вряд ли ответ здесь будет «на всякий случай, вдруг понадобится». Сам бы хотел узнать от более опытных товарищей. Ну и последнее, далее появился еще JAX-RS для так называемых RESTful веб-сервисов, но это тема отдельной статьи. На этом введение можно заканчивать, т.к. далее мы будем учиться работать с JAX-WS.

Общий подход

В веб-сервисах всегда есть клиент и сервер. Сервер – это и есть наш веб-сервис и иногда его называют endpoint (типа как, конечная точка, куда доходят SOAP сообщения от клиента). Нам нужно сделать следующее:
  1. Описать интерфейс нашего веб-сервиса
  2. Реализовать этот интерфейс
  3. Запустить наш веб-сервис
  4. Написать клиента и удаленно вызвать нужный метод веб-сервиса
Запуск веб-сервиса можно производить разными способами: либо описать класс с методом main и запустить веб-сервис непосредственно, как сервер, либо задеплоить его на сервер типа Tomcat или любой другой. Во втором случае мы сами не запускаем новый сервер и не открываем еще один порт на компьютере, а просто говорим контейнеру сервлетов Tomcat, что «мы написали тут классы веб-сервиса, опубликуй их, пожалуйста, чтобы все, кто к тебе обратиться, могли нашим веб-сервисом воспользоваться». В независимости от способа запуска веб-сервиса, клиент у нас будет один и тот же.

Сервер

Запустим IDEA и создадим новый проект Create New Project . Укажем имя HelloWebService и нажмем кнопку Next , далее кнопку Finish . В папке src создадим пакет ru.javarush.ws . В этом пакете создадим интерфейс HelloWebService: package ru. javarush. ws; // это аннотации, т.е. способ отметить наши классы и методы, // как связанные с веб-сервисной технологией import javax. jws. WebMethod; import javax. jws. WebService; import javax. jws. soap. SOAPBinding; // говорим, что наш интерфейс будет работать как веб-сервис @WebService // говорим, что веб-сервис будет использоваться для вызова методов @SOAPBinding (style = SOAPBinding. Style. RPC) public interface HelloWebService { // говорим, что этот метод можно вызывать удаленно @WebMethod public String getHelloString (String name) ; } В этом коде классы WebService и WebMethod являются так называемыми аннотациям и ничего не делают, кроме как помечают наш интерфейс и его метод, как веб-сервис. Это же относится и к классу SOAPBinding . Разница лишь в том, что SOAPBinding – это аннотация с параметрами. В данном случае используется параметр style со значением, говорящим, что веб-сервис будет работать не через сообщения-документы, а как классический RPC, т.е. для вызова метода. Давайте реализуем логику нашего интерфейса и создадим в нашем пакете класс HelloWebServiceImpl . Кстати, замечу, что окончание класса на Impl – это соглашение в Java, по которому так обозначают реализацию интерфейсов (Impl – от слова implementation, т.е. реализация). Это не требование и вы вольны назвать класс как хотите, но правила хорошего тона того требуют: package ru. javarush. ws; // таже аннотация, что и при описании интерфейса, import javax. jws. WebService; // но здесь используется с параметром endpointInterface, // указывающим полное имя класса интерфейса нашего веб-сервиса @WebService (endpointInterface = "ru.javarush.ws.HelloWebService" ) public class HelloWebServiceImpl implements HelloWebService { @Override public String getHelloString (String name) { // просто возвращаем приветствие return "Hello, " + name + "!" ; } } Запустим наш веб-сервис как самостоятельный сервер, т.е. без участия всяких Tomcat и серверов приложений (это тема отдельного разговора). Для этого в структуре проекта в папке src создадим пакет ru.javarush.endpoint , а в нем создадим класс HelloWebServicePublisher с методом main: package ru. javarush. endpoint; // класс, для запуска веб-сервера с веб-сервисами import javax. xml. ws. Endpoint; // класс нашего веб-сервиса import ru. javarush. ws. HelloWebServiceImpl; public class HelloWebServicePublisher { public static void main (String. . . args) { // запускаем веб-сервер на порту 1986 // и по адресу, указанному в первом аргументе, // запускаем веб-сервис, передаваемый во втором аргументе Endpoint. publish ("http://localhost:1986/wss/hello" , new HelloWebServiceImpl () ) ; } } Теперь запустим этот класс, нажав Shift+F10 . В консоли ничего не появится, но сервер запущен. В этом можно убедиться набрав в браузере строку http://localhost:1986/wss/hello?wsdl . Открывшаяся страница, с одной стороны, доказывает, что у нас на компьютере (localhost) запустился веб-сервер (http://) на порту 1986, а, с другой стороны, показывает WSDL описание нашего веб-сервиса. Если вы остановите приложение, то описание станет недоступно, как и сам веб-сервис, поэтому делать этого не будем, а перейдем к написанию клиента.

Клиент

В папке проекта src создадим пакет ru.javarush.client , а в нем класс HelloWebServiceClient с методом main: package ru. javarush. client; // нужно, чтобы получить wsdl описание и через него // дотянуться до самого веб-сервиса import java. net. URL; // такой эксепшн возникнет при работе с объектом URL import java. net. MalformedURLException; // классы, чтобы пропарсить xml-ку c wsdl описанием // и дотянуться до тега service в нем import javax. xml. namespace. QName; import javax. xml. ws. Service; // интерфейс нашего веб-сервиса (нам больше и нужно) import ru. javarush. ws. HelloWebService; public class HelloWebServiceClient { public static void main (String args) throws MalformedURLException { // создаем ссылку на wsdl описание URL url = new URL ("http://localhost:1986/wss/hello?wsdl" ) ; // Параметры следующего конструктора смотрим в самом первом теге WSDL описания - definitions // 1-ый аргумент смотрим в атрибуте targetNamespace // 2-ой аргумент смотрим в атрибуте name QName qname = new QName ("http://ws.сайт/" , "HelloWebServiceImplService" ) ; // Теперь мы можем дотянуться до тега service в wsdl описании, Service service = Service. create (url, qname) ; // а далее и до вложенного в него тега port, чтобы // получить ссылку на удаленный от нас объект веб-сервиса HelloWebService hello = service. getPort (HelloWebService. class ) ; // Ура! Теперь можно вызывать удаленный метод System. out. println (hello. getHelloString ("JavaRush" ) ) ; } } Максимум комментариев по коду я дал в листинге. Добавить мне нечего, поэтому запускаем (Shift+F10). Мы должны в консоли увидеть текст: Hello, JavaRush! Если не увидели, то видимо забыли запустить веб-сервис.

Заключение

В данном топике был представлен краткий экскурс в веб-сервисы. Еще раз скажу, что многое из того, что я написал – это мои догадки по поводу того, как это работает, и поэтому мне не стоит сильно доверять. Буду признателен, если знающие люди меня поправят, ведь тогда я чему-нибудь научусь. UPD.

История создания

С появлением персональных компьютеров появилась и необходимость их объединения. Сначала были простые кабельные соединения, потом появились сетевые протоколы объединяющие компьютеры работающие на одной ОС, с развитием технологий отпала необходимость иметь одну ОС на всех компьютерах и появилась возможность объединения компьютеров работающих под разными ОС. Интернет изменил скорость движения по пути объединения.

Но и на сегодняшний день еще не все проблемы интеграции решены к сожалению не было единого протокола для коммуникационной связи между Интернет-приложениями и сервисами. Для решения этой проблемы объединились такие компании как Microsoft, DevelopMentor, UserLand Software, IBM и Lotus Development и в результате их совместной деятельности получился (Simple Object Access Protocol) простой протокол доступа к объектам описывает стандарт удаленного вызова процедур на основе языка XML (Extensible Markup Language - расширяемый язык разметки). SOAP призван предельно упростить разработку межъязыковых приложений и средств интеграции бизнеса. Начало было положено SOAP 1.0 для работы которого требовался протокол НТТР.

После появления начальной версии SOAP, созданной, как уже отмечалось, объединенными усилиями Microsoft, DevelopMentor и UserLand, к разработке продукта подключились IBM и Lotus. В результате спецификация подверглась существенной переделке и стала лучше подходить для интеграции разнородных сред. Главным отличием следующей версии SOAP 1.1 от начальной версии стал переход с XML-Data корпорации Microsoft на XML Schema. К тому же в новом варианте спецификация перестала зависеть от транспортных протоколов. Для работы SOAP 1.0 требовался протокол НТТР, тогда как для SOAP 1.1 разновидность транспорта значения не имеет: для пересылки сообщений можно воспользоваться электронной почтой или указателями на очереди сообщений (massage queving links). Компании, уже взявшие на вооружение SOAP 1.0, оказались привязанными к нестандартной технологии Microsoft. Впрочем, ряд перспективных продуктов этой корпорации, включая BizTalk Server и SQL Server 7.0, также опирается на XML-Data. С появлением версии 1.1 круг сторонников протокола SOAP расширяется

Первоначальная версия SOAP 1.1, представленная в Целевую группу технической поддержки Интернета IETF, имела в своей основе технологию XML-Data, предложенную корпорацией Microsoft в январе 1998 г. Однако в процессе рассмотрения стандартов в консорциуме W3C базовая структура была заменена на XML Schema. World Wide Web Consortium было предложено рассмотреть SOAP 1.1 в качестве потенциального стандарта.

Новейшая версия спецификации протокола Simple Object Access Protocol (SOAP) доступна на веб-сервере, обслуживающем участников программы MSDN™ для разработчиков (http://msdn.microsoft.com/). SOAP - это открытый, построенный на стандартах протокол, который определяет на основе XML (Extensible Markup Language) общий формат для коммуникационной связи между любыми Интернет-приложениями и сервисами. Эта версия расширяет возможности SOAP в асинхронной коммуникационной связи и теперь включает поддержку не только HTTP, но и таких Интернет-протоколов, как SMTP, FTP и TCP/IP. Последняя версия спецификации SOAP встретила широкую поддержку со стороны таких компаний, как ActiveState Tool Corp., Ariba Inc., BORN Information Services Inc., Commerce One Inc., Compaq Computer Corp., DevelopMentor Inc., Extensibility Inc., IBM, IONA Technologies PLC, Intel Corp., Lotus Development Corp., ObjectSpace Inc., Rogue Wave Software Inc., Scriptics Corp., Secret Labs AB, UserLand Software и Zveno Pty. Ltd. Спецификация SOAP предоставляет общий механизм для интеграции сервисов в Интернете и/или интрасетях независимо от применяемой операционной системы, модели объектов или языка программирования. Основанный на Интернет-стандартах XML и HTTP, протокол SOAP позволяет взаимодействовать друг с другом любым новым или существующим приложениям. Web-узлы, поддерживающие SOAP, могут стать Web- сервисами, доступными чисто программным путем и не требующими участия человека. Единая инфраструктура, обеспечивающая прямое взаимодействие связанных с Интернетом приложений, открывает новые возможности в интеграции сервисов и устройств - в какой бы точке Интернета они ни находились.

Веб-сервисы и SOAP

Веб-сервисы и SOAP призваны решить проблемы кросс-платформенного взаимодействия приложений. Статья поможет получить представление об этих новых перспективных технологиях.

Что такое SOAP

В настоящее время используемые технологии удаленного вызова методов (DCOM, CORBA/IIOP и RMI) довольно сложны в настройке и организации взаимодействия. Это влечет за собой проблемы в эксплуатации и функционировании распределенных систем (проблемы безопасности, транспорт через брандмауэры и т.д.). Существующие проблемы успешно решены созданием SOAP (Simple Object Access Protocol), простого протокола, основанного на XML, для обмена сообщениями в распределенных средах (WWW). Он предназначен для создания веб-сервисов и удаленного вызова методов. SOAP можно использовать с разными транспортными протоколами, включая HTTP, SMTP и т.д.

Что такое веб-сервисы

Веб-сервисы - это функциональность и данные, предоставляемые для использования внешними приложениями, которые работают с сервисами посредством стандартных протоколов и форматов данных. Веб-сервисы полностью независимы от языка и платформы реализации. Технология веб-сервисов является краеугольным камнем программной модели Microsoft .NET. Для демонстрации возможностей SOAP я использовал недавно вышедшую реализацию SOAP Toolkit версии 2.0 от Microsoft. Следует заметить, что текущая версия Toolkit заметно отличается от предыдущей (Microsoft SOAP Toolkit for Visual Studio 6.0) и от бета версии SOAP Toolkit 2.0.

Механизм взаимодействия клиента и сервера

  1. Клиентское приложение создает экземпляр объекта SOAPClient
  2. SOAPClient читает файлы описания методов веб-сервиса (WSDL и Web Services Meta Language - WSML). Эти файлы могут храниться и на клиенте.
  3. Клиентское приложение, используя возможности позднего связывания методов объекта SOAPClient, вызывает метод сервиса. SOAPClient формирует пакет запроса (SOAP Envelope) и отправляет на сервер. Возможно использование любого транспортного протокола, но, как правило, используется HTTP.
  4. Пакет принимает серверное приложение Listener (может представлять собой ISAPI приложение или ASP страницу), создает объект SOAPServer и передает ему пакет запроса
  5. SOAPServer читает описание веб-сервиса, загружает описание и пакет запроса в XML DOM деревья
  6. SOAPServer вызывает метод объекта/приложения, реализующего сервис
  7. Результаты выполнения метода или описание ошибки конвертируются объектом SOAPServer в пакет ответа и отправляются клиенту
  8. Объект SOAPClient проводит разбор принятого пакета и возвращает клиентскому приложению результаты работы сервиса или описание возникшей ошибки.

WSDL файл это документ в формате XML, описывающий методы, предоставляемые веб-сервисом. Также параметры методов, их типы, названия и местонахождение Listener`а сервиса. SOAP Toolkit визард автоматически генерирует этот документ.

SOAP Envelope (Пакет) - XML документ, который содержит в себе запрос/ответ на выполнение метода. Удобнее всего рассматривать его как почтовый конверт, в который вложена информация. Тэг Envelope должен быть корневым элементом пакета. Элемент Header не обязателен, а Body должен присутствовать и быть прямым потомком элемента Envelope. В случае ошибки выполнения метода сервер формирует пакет, содержащий в тэге Body элемент Fault, который содержит подробное описание ошибки. Если вы пользуетесь высокоуровневыми интерфейсами SOAPClient, SOAPServer, то вам не придется вдаваться в тонкости формата пакета, но, при желании, можно воспользоваться низкоуровневыми интерфейсами или же вообще создать пакет "руками".

Объектная модель SOAP Toolkit дает возможность работать с объектами низкоуровневого API:

  • SoapConnector - Обеспечивает работу с транспортным протоколом для обмена SOAP пакетами
  • SoapConnectorFactory - Обеспечивает метод создания коннектора для транспортного протокола, указанного в WSDL файле (тэг)
  • SoapReader - Читает SOAP сообщения и строит XML DOM деревья
  • SoapSerializer - Содержит методы создания SOAP сообщения
  • IsoapTypeMapper, SoapTypeMapperFactory - Интерфейсы, позволяющие работать со сложными типами данных

Используя объекты высокоуровневого API можно передавать данные только простых типов (int, srting, float …), но спецификация SOAP 1.1 допускает работу с более сложными типами данных, например с массивами, структурами, списками и их комбинациями. Для работы с такими типами приходится использовать интерфейсы IsoapTypeMapper и SoapTypeMapperFactory.

hats 23 июля 2013 в 13:09

Пишем SOAP клиент-серверное приложение на PHP

  • PHP
  • Tutorial

Всем привет!
Так случилось, что в последнее время я стал заниматься разработкой веб-сервисов. Но сегодня топик не обо мне, а о том, как нам написать свой XML Web Service основанный на протоколе SOAP 1.2.

Я надеюсь, что после прочтения топика вы сможете самостоятельно:

  • написать свою собственную серверную реализацию веб-приложения;
  • написать свою собственную клиентскую реализацию веб-приложения;
  • написать свое собственное описание веб-сервиса (WSDL);
  • отправлять клиентом массивы однотипных данных на сервер.
Как вы могли догадаться, вся магия будет твориться с использованием PHP и встроенных классов SoapClient и SoapServer. В качестве кролика у нас будет выступать сервис по отправке sms-сообщений.

1 Постановка задачи

1.1 Границы

В начале предлагаю разобраться с тем результатом, которого мы достигнем в конце топика. Как было объявлено выше, мы будем писать сервис по отправке sms-сообщений, а если еще точнее, то к нам будут поступать сообщения из разных источников по протоколу SOAP. После чего, мы рассматрим в каком виде они приходят на сервер. Сам процесс постановки сообщений в очередь для их дальнейшей отправки провайдеру, к сожалению, выходит за рамки данного поста по многим причинам.

1.2 Какими данными будем меняться?

Отлично, с границами мы определились! Следующий шаг, который необходимо сделать – решить какими данными мы будем обмениваться между сервером и клиентом. На эту тему предлагаю долго не мудрить и сразу для себя ответить на главные вопросы:
  • Какой минимум данных надо посылать на сервер, чтобы отправить sms-сообщение абоненту?
  • Какой минимум данных надо посылать с сервера, чтобы удовлетворить потребности клиента?
Что-то мне подсказывает, что для этого необходимо посылать следующее: В принципе, двух этих характеристик достаточно для отправки, но мне сразу представляется случай, как sms-ка с поздравлением о дне рождения приходит вам в 3 часа утра, или 4! В этот момент я буду всем очень благодарен за то, что про меня не забыли! Поэтому, мы также будем посылать на сервер и
  • дату отправки sms-сообщения.
Следующее, что я бы хотел отправлять на сервер, так это
  • Тип сообщения.
Данный параметр не является обязательным, но он может нам очень сильно пригодиться в случае, если быстро понадобится сказать боссу о том, скольких из наших клиентов мы «обрадовали» своим известием, а также нарисовать какую-нибудь красивую статистику на этот счет.

И все же, я что-то забыл! Если еще немного порефлексировать, то стоит отметить, что клиент за раз может отправить на сервер как одно sms-сообщение, так и некоторое их количество. Другими словами, в одном пакете данных может быть от одного до бесконечности сообщений.

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

  • номер мобильного телефона,
  • текст sms-сообщения,
  • время отправки sms-сообщения абоненту,
  • тип сообщения.

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

  • TRUE – пакет успешно дошел до сервера, прошел аутентификацию и встал в очередь для отправки sms-провайдеру
  • FALSE – во всех остальных случаях

На этом мы закончили описание постановки задачи! И наконец-то приступим к самому интересному – будем разбираться что за диковинный зверь этот SOAP!

2 С чем есть SOAP?

Вообще, изначально я не планировал ничего писать о том, что такое SOAP и хотел ограничиться ссылками на сайт w3.org с нужными спецификациями, а также ссылками на Wikipedia. Но в самом конце решил написать коротенькую справочку об этом протоколе.

И начну я свое повествование с того, что данный протокол обмена данными относится к подмножеству протоколов основанных на так называемой парадигме RPC (Remote Procedure Call, удалённый вызов процедур) антиподом которой является REST (Representational State Transfer, передача репрезентативного состояния). Более подробно об этом можно прочесть в Wikipedia, ссылки на статьи находятся в самом конце топика. Из этих статей нам надо уяснить следующее: «Подход RPC позволяет использовать небольшое количество сетевых ресурсов с большим количеством методов и сложным протоколом. При подходе REST количество методов и сложность протокола строго ограничены, из-за чего количество отдельных ресурсов может быть большим». Т.е., применительно к нам это означает, что на сайте в случае RPC подхода будет всегда один вход (ссылка) на сервис и какую процедуру вызывать для обработки поступающих данных мы передаем вместе с данными, в то время как при REST подходе на нашем сайте есть много входов (ссылок), каждая из которых принимает и обрабатывает только определенные данные. Если кто-то из читающих знает, как еще проще объяснить различие в данных подходах, то обязательно пишите в комментариях!

Следующее, что нам надо узнать про SOAP – данный протокол в качестве транспорта использует тот самый XML, что с одной стороны очень хорошо, т.к. сразу же в наш арсенал попадает вся мощь стека технологий основанных на данном языке разметки, а именно XML-Schema – язык описания структуры XML-документа (спасибо Wikipedia!), который позволяет производит автоматическую валидацию поступающих на сервер данных от клиентов.

И так, теперь мы знаем, что SOAP – протокол используемый для реализации удаленного вызова процедур и в качестве транспорта он использует XML! Если почитать статью на Wikipedia, то оттуда можно узнать еще и о том, что он может использоваться поверх любого протокола прикладного уровня, а не только в паре с HTTP (к сожалению, в данном топике мы будем рассматривать только SOAP поверх HTTP). И знаете, что мне во всем этом больше всего нравится? Если нет никаких догадок, то я дам подсказку – SOAP!… Всеравно не появилось догадок?… Вы точно прочли статью на Wikipedia?… В общем, не буду вас дальше мучить. Поэтому, сразу перейду к ответу: «SOAP (от англ. Simple Object Access Protocol - простой протокол доступа к объектам; вплоть до спецификации 1.2 )». Самое примечательное в этой строчке выделено курсивом! Я не знаю какие выводы сделали вы из всего этого, но мне видится следующее – поскольку данный протокол ну никак нельзя назвать «простым» (и видимо с этим согласны даже в w3), то с версии 1.2 он вообще перестал как-то расшифровываться! И стал называться SOAP, просто SOAP и точка.

Ну да ладно, прошу меня извинить, занесло немного в сторону. Как я писал ранее, в качестве транспорта используется XML, а пакеты, которые курсируют между клиентом и сервером называются SOAP-конвертами. Если рассматривать обобщенную структуру конверта, то он вам покажется очень знакомым, т.к. напоминает структуру HTML-страницы. В нем есть основной раздел – Envelop , который включает разделы Header и Body , либо Fault . В Body передаются данные и он является обязательным разделом конверта, в то время как Header является опциональным. В Header может передаваться авторизация, либо какие-либо иные данные, которые на прямую не относятся к входным данным процедур веб-сервиса. Про Fault особо рассказывать нечего, кроме того, что он приходит в клиент с сервера в случае возникновения каких-либо ошибок.

На этом мой обзорный рассказ про протокол SOAP заканчивается (более детально сами конверты и их структуру мы рассмотрим когда наши клиент и сервер наконец-то научатся запускать их друг в друга) и начинается новый – про компаньона SOAP под названием WSDL (Web Services Description Language). Да-да, это та самая штука, которая отпугивает большинство из нас от самой попытки взять и реализовать свое API на данном протоколе. В результате чего, мы обычно изобретаем свой велосипед с JSON в качестве транспорта. И так, что такое WSDL? WSDL – язык описания веб-сервисов и доступа к ним, основанный на языке XML (с) Wikipedia. Если из этого определения вам не становится понятным весь сакральный смысл данной технологии, то я попытаюсь описать его своими словами!

WSDL предназначен для того, чтобы наши клиенты могли нормально общаться с сервером. Для этого в файле с расширением «*.wsdl» описывается следующая информация:

  • Какие пространства имен использовались,
  • Какие схемы данных использовались,
  • Какие типы сообщений веб-сервис ждет от клиентов,
  • Какие данные принадлежат каким процедурам веб-сервиса,
  • Какие процедуры содержит веб-сервис,
  • Каким образом клиент должен вызывать процедуры веб-сервиса,
  • На какой адрес должны отправляться вызовы клиента.
Как видно, данный файл и есть весь веб-сервис. Указав в клиенте адрес WSDL-файла мы будем знать об любом веб-сервисе все! В результате, нам не надо абсолютно ничего знать о том, где расположен сам веб-сервис. Достаточно знать адрес расположения его WSDL-файла! Скоро мы узнаем, что не так страшен SOAP как его малюют (с) русская пословицы.

3 Введение в XML-Schema

Теперь мы много чего знаем о то, что такое SOAP, что находится у него внутри и имеем обзорное представление о том, какой стек технологий его окружает. Поскольку, прежде всего SOAP представляет собой способ взаимодействия между клиентом и сервером, и в качестве транспорта для него используется язык разметки XML, то в данном разделе мы немного разберемся каким образом происходит автоматическая валидация данных посредством XML-схем.

Основная задачи схемы – описать структуру данных которые мы собираемся обрабатывать. Все данные в XML-схемах делятся на простые (скалярные) и коплексные (структуры) типы. К простым типам относятся такие типы как:

  • строка,
  • число,
  • булево значение,
  • дата.
Что-то очень простое, у чего внутри нет расширений. Их антиподом являются сложные комплексные типы. Самый простой пример комплексного типа, который приходит всем в голову – объекты. Например, книга. Книга состоит из свойств: автор , название , цена , ISBN номер и т.д. И эти свойства, в свою очередь, могут быть как простыми типами, так и комплексными. И задача XML-схемы это описать.

Предлагаю далеко не ходить и написать XML-схему для нашего sms-сообщения! Ниже представлено xml-описание sms-сообщения:

71239876543 Тестовое сообщение 2013-07-20T12:00:00 12
Схема нашего комплексного типа будет выглядеть следующим образом:


Эта запись читается следующим образом: у нас есть переменная «message » типа «Message » и есть комплексный тип с именем «Message », который состоит из последовательного набора элементов «phone » типа string , «text » типа string , «date » типа dateTime , «type » типа decimal . Эти типы простые и уже определены в описании схемы. Поздравляю! Мы только что написали нашу первую XML-схему!

Думаю, что значение элементов «element » и «complexType » вам стало все более-менее понятно, поэтому не будем на них больше заострять внимание и переключимся сразу же на элемент-композитор «sequence ». Когда мы используем элемент-композитор «sequence » мы сообщаем о том, что элементы включенные в него должны всегда располагаться в указанной в схеме последовательности, а также все из них являются обязательными. Но не стоит отчаиваться! В XML-схемах есть еще два элемента-композитора: «choice » и «all ». Композитор «choice » сообщает о том, что должен быть какой-то один из перечисленных в нем элементов, а композитор «all » – любая комбинация перечисленных элементов.

Как вы помните, то в первом разделе топика мы договорились о том, что в пакете может передаваться от одного до бесконечности sms-сообщений. Поэтому предлагаю разобраться как такие данные декларируются в XML-схеме. Общая структура пакета может выглядеть следующим образом:

71239876543 Тестовое сообщение 1 2013-07-20T12:00:00 12 71239876543 Тестовое сообщение N 2013-07-20T12:00:00 12
Схема для такого комплексного типа будет выглядеть так:


В первом блоке идет знакомое нам декларирование комплексного типа «Message ». Если вы заметили, то в каждом простом типе, входящем в «Message », были добавлены новые уточняющие атрибуты «minOccurs » и «maxOccurs ». Как не трудно догадаться из названия, первый (minOccurs ) сообщает о том, что в данной последовательности должно быть минимум по одному элементу типа «phone », «text », «date » и «type », в то время как следующий (maxOccurs ) атрибут нам декларирует, что таких элементов в нашей последовательности максимум по-одному. В результате, когда мы пишем свои схемы для каких-либо данных, нам предоставляется широчайший выбор по их настройке!

Второй блок схемы декларирует элемент «messageList » типа «MessageList ». Видно, что «MessageList » представляет собой комплексный тип, который включает минимум один элемент «message », но максимальное число таких элементов не ограничено!

4 Пишем свой WSDL

Вы помните о том, что WSDL и есть наш веб-сервис? Надеюсь, что помните! Как мы его напишем, так на нем наш маленький веб-сервис и поплывет. Поэтому, предлагаю не халтурить.

Вообще, для того, чтобы у нас все работало правильно нам надо передавать клиенту WSDL-файл с правильным MIME-типом. Для этого необходимо настроить ваш веб-сервер соответствующим образом, а именно – установить для файлов с расширением «*.wsdl» MIME-тип равный следующей строке:

Application/wsdl+xml
Но на практике, я обычно отправлял посредством PHP HTTP-заголовок«text/xml »:

Header("Content-Type: text/xml; charset=utf-8");
и все прекрасно работало!

Хочу сразу предупредить, наш простенький веб-сервис будет иметь довольно внушительное описание, поэтому не пугайтесь, т.к. большая часть текста является обязательной водой и написав ее один раз можно постоянно копировать от одного веб-сервиса к другому!

Поскольку WSDL – это XML, то в самой первой строке необходимо прямо об этом и написать. Корневой элемент файла всегда должен называться «definitions »:


Обычно, WSDL состоит из 4-5 основных блоков. Самый первый блок – определение веб-сервиса или другими словами – точки входа.


Здесь написано, что у нас есть сервис, который называется – «SmsService ». В принципе, все имена в WSDL-файле могут быть вами изменены на какие только пожелаете, т.к. они не играют абсолютно никакой роли.

После этого мы объявляем о том, что в нашем веб-сервисе «SmsService » есть точка входа («port»), которая называется «SmsServicePort ». Именно в эту точку входа и будут отправляться все запросы от клиентов к серверу. И указываем в элементе «address » ссылку на файл-обработчик, который будет принимать запросы.

После того, как мы определили веб-сервис и указали для него точку входа – необходимо привязать к нему поддерживаемые процедуры:


Для этого перечисляется какие операции и в каком виде у будут вызываться. Т.е. для порта «SmsServicePort » определена привязка под именем «SmsServiceBinding », которая имеет тип вызова «rpc » и в качестве протокола передачи (транспорта) используется HTTP. Т.о., мы здесь указали, что будем осуществлять RPC вызов поверх HTTP. После этого мы описываем какие процедуры (operation ) поддерживаются в веб-сервисе. Мы будем поддерживать всего одну процедуру – «sendSms ». Через эту процедуру будут отправляться на сервер наши замечательные сообщения! После того, как была объявлена процедура, необходимо указать в каком виде будут передаваться данные. В данном случае указано, что будут использоваться стандартные SOAP-конверты.

После этого нам необходимо привязать процедуру к сообщениям:


Для этого мы указываем, что наша привязка («binding») имеет тип «SmsServicePortType » и в элементе «portType » с одноименным типу именем указываем привязку процедур к сообщениям. И так, входящее сообщение (от клиента к серверу) будет называться «sendSmsRequest », а исходящее (от сервера к клиенту) «sendSmsResponse ». Как и все имена в WSDL, имена входящих и исходящих сообщения – произвольные.

Теперь нам необходимо описать сами сообщения, т.е. входящие и исходящие:


Для этого мы добавляем элементы «message » с именами «sendSmsRequest » и «sendSmsResponse » соответственно. В них мы указываем, что на вход должен прийти конверт, структура которого соответствует типу данных «Request ». После чего с сервера возвращается конверт содержащий тип данных – «Response ».

Теперь надо сделать самую малость – добавить описание данных типов в наш WSDL-файл! И как вы думаете, как описываются в WSDL входящие и исходящие данные? Думаю, что вы уже все давно поняли и сказали сами себе, что при помощи XML-схем! И вы будете абсолютно правы!


Можно нас поздравить! Наш первый WSDL был написан! И мы еще на один шаг приблизились к достижению поставленной цели.
Далее мы разберемся с тем, что нам предоставляет PHP для разработки собственных распределенных приложений.

5 Наш первый SOAP-сервер

Ранее я писал, что для создания SOAP-сервера на PHP мы будем использовать встроенный класс SoapServer. Для того, чтобы все дальнейшие действия происходили также как и у меня, вам понадобиться немного подкрутить свой PHP. Если быть еще точнее, то необходимо убедиться, что у вас установлено расширение «php-soap». Как его поставить на ваш веб-сервере лучше всего прочитать на официальном сайте PHP (см. список литературы).

После того, как все было установлено и настроено нам необходимо будет создать в корневой папке вашего хостинга файл «smsservice.php » со следующим содержанием:

setClass("SoapSmsGateWay"); //Запускаем сервер $server->handle();
То, что находится выше строчки с функцией «ini_set», надеюсь, что объяснять не надо. Т.к. там определяется какие HTTP-заголовки мы будем отправлять с сервера клиенту и настраивается окружение. В строчке с «ini_set» мы отключаем кеширование WSDL-файла для того, чтобы наши изменения в нем сразу же вступали в действие на клиенте.

Теперь мы подошли к серверу! Как видим, весь SOAP-сервер занимает всего лишь три строки! В первой строке мы создаем новый экземпляр объекта SoapServer и передаем ему в конструктор адрес нашего WSDL-описания веб-сервиса. Теперь мы знаем, что он будет располагаться в корне хостинга в файле с говорящим именем «smsservice.wsdl.php ». Во второй строке мы сообщаем SOAP-серверу какой класс необходимо дергать для того, чтобы обработать поступивший с клиента конверт и вернуть конверт с ответом. Как вы могли догадаться, именно в этом классе будет описан наш единственный метод sendSms . В третьей строке мы запускаем сервер! Все, наш сервер готов! С чем я нас всех и поздравляю!

Теперь нам необходимо создать WSDL-файл. Для этого можно либо просто скопировать его содержимое из предыдущего раздела, либо позволить себе вольности и немного его «шаблонизировать»:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
На этом этапе получившийся сервер нас должен устроить полностью, т.к. поступающие к нему конверты мы можем логировать и потом спокойно анализировать приходящие данные. Для того, чтобы мы могли что-либо получать на сервер, нам необходим клиент. Поэтому давайте им и займемся!

6 SOAP-клиент на подходе

Прежде всего нам надо создать файл, в котором будем писать клиент. Как обычно, мы его создадим в корне хоста и назовем «client.php », а внутри напишем следующее:

messageList = new MessageList(); $req->messageList->message = new Message(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Тестовое сообщение 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://{$_SERVER["HTTP_HOST"]}/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
Опишем наши объекты. Когда мы писали WSDL в нем для входящего на сервер конверта описывались три сущности: Request , MessageList и Message . Соответственно классы Request , MessageList и Message являются отражениями этих сущностей в нашем PHP-скрипте.

После того, как мы определили объекты, нам необходимо создать объект ($req ), который будем отправлять на сервер. После чего идут две самые заветные для нас строки! Наш SOAP-клиент! Верите или нет, но этого достаточно для того, чтобы на наш сервер начали сыпаться сообщения от клиента, а также для того, чтобы наш сервер успешно их принимал и обрабатывал! В первой из них мы создаем экземпляр класса SoapClient и передаем в его конструктор адрес расположения WSDL-файла, а в параметрах явно указываем, что работать мы будем по протоколу SOAP версии 1.2. В следующей строке мы вызываем метод sendSms объекта $client и сразу же выводим в браузере результат.
Давайте запусти и посмотрим что-же у нас наконец-то получилось!

Мне с сервера вернулся следующий объект:

Object(stdClass) public "status" => boolean true
И это замечательно, т.к. теперь мы точно знаем о том, что наш сервер работает и не просто работает, но еще и может возвращать на клиент какие-то значения!

Теперь посмотрим на лог, который мы предусмотрительно ведем на серверной стороне! В первой его части мы видим необработанные данные, которые поступили на сервер:

79871234567 Тестовое сообщение 1 2013-07-21T15:00:00.26 15
Это и есть конверт. Теперь вы знаете как он выглядит! Но постоянно на него любоваться нам вряд ли будет интересно, поэтому давайте десереализуем объект из лог-файла и посмотрим все ли у нас хорошо:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
Как видим, объект десериализовался правильно, с чем я нас всех хочу поздравить! Далее нас ждет что-то более интересно! А именно – мы будем отправлять клиентом на сервер не одно sms-сообщение, а целую пачку (если быть точнее, то целых три)!

7 Отправляем сложные объекты

Давайте подумаем над тем, как же нам передать целую пачку сообщений на сервер в одном пакете? Наверно, самым простым способом будет организация массива внутри элемента messageList! Давайте это сделаем:

// создаем объект для отправки на сервер $req = new Request(); $req->messageList = new MessageList(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Тестовое сообщение 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Тестовое сообщение 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Тестовое сообщение 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
В наших логах числится, что пришел следующий пакет от клиента:

79871234567 Тестовое сообщение 1 2013-07-21T15:00:00.26 15 79871234567 Тестовое сообщение 2 2014-08-22T16:01:10 16 79871234567 Тестовое сообщение 3 2014-08-22T16:01:10 17
Что за ерунда, скажете вы? И будете правы в некотором смысле, т.к. только что мы узнали о том, что какой объект ушел от клиента, то абсолютно в том же виде он пришел к нам на сервер в виде конверта. Правда, sms-сообщения сериализовались в XML не так, как нам было необходимо – они должны были быть обернуты в элементы message , а не в Struct . Теперь посмотрим в каком виде приходит такой объект в метод sendSms :

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 2" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "17" (length=2)
Что нам дает это знание? Только то, что выбранный нами путь не является верным и мы не получили ответа на вопрос – «Как нам на сервере получить правильную структуру данных?». Но я предлагаю не отчаиваться и попробовать привести наш массив к типу объект :

$req->messageList->message = (object)$req->messageList->message;
В этом случае, нам придет уже другой конверт:

79871234567 Тестовое сообщение 1 2013-07-21T15:00:00.26 15 79871234567 Тестовое сообщение 2 2014-08-22T16:01:10 16 79871234567 Тестовое сообщение 3 2014-08-22T16:01:10 17
Пришедший в метод sendSms объект имеет следующую структуру:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 2" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "17" (length=2)
Как по мне, то «от перемены мест слагаемых – сумма не меняется» (с). Что BOGUS , что Struct – цель нами до сих пор не достигнута! А для ее достижения нам необходимо сделать так, чтобы вместо этих непонятных названий отображалось наше родное message . Но как этого добиться, автору пока не известно. Поэтому единственное, что мы можем сделать – избавить от лишнего контейнера. Другими словами, мы сейчас сделаем так, чтобы вместо message стал BOGUS ! Для этого изменим объект следующим образом:

// создаем объект для отправки на сервер $req = new Request(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Тестовое сообщение 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Тестовое сообщение 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Тестовое сообщение 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
Вдруг нам повезет и из схемы подтянется правильное название? Для этого посмотрим на пришедший конверт:

79871234567 Тестовое сообщение 1 2013-07-21T15:00:00.26 15 79871234567 Тестовое сообщение 2 2014-08-22T16:01:10 16 79871234567 Тестовое сообщение 3 2014-08-22T16:01:10 17
Да, чуда не произошло! BOGUS – не победим! Пришедший в sendSms объект в этом случае будет выглядеть следующим образом:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 2" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Тестовое сообщение 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "17" (length=2)
Как говорится – «Почти»! На этой (немного печальной) ноте предлагаю потихонечку закругляться и сделать некоторые для себя выводы.

8 Заключение

Наконец-то мы добрались сюда! Давайте определимся с тем, что вы теперь умеете делать:
  • вам по силам написать необходимый для вашего веб-сервиса WSDL-файл;
  • вы без всяких проблем можете написать свой собственный клиент способный общаться с сервером по протоколу SOAP;
  • вы можете написать свой собственный сервер общающийся с окружающим миром по SOAP;
  • вы можете отправлять массивы однотипных объектов на сервер со своего клиента (с некоторыми ограничениями).
Также, мы сделали для себя некоторые открытия в ходе нашего небольшого исследования:
  • нативный класс SoapClient не умеет правильно сериализовывать однотипные структуры данных в XML;
  • при сериализации массива в XML он создает лишний элемент с именем Struct ;
  • при сериализации объекта в XML он создает лишний элемент с именем BOGUS ;
  • BOGUS меньшее зло чем Struct из-за того, что конверт получается компактнее (не добавляются лишние namespace"ы в XML заголовке конверта);
  • к сожалению, класс SoapServer автоматически не валидирует данные конверта нашей XML-схемой (возможно, и другие сервера этого не делают).

Как уже говорилось в предыдущей главе, Web-службы обмениваются информацией с клиентами и между собой, посылая сообщения на языке XML. Теги этой реализации XML, правила оформления документа XML и порядок обмена документами определены протоколом SOAP. Протокол SOAP создан в 1998 году командой разработчиков под руководством Дейва Винера (Dave Winer), работавшей в корпорации Microsoft и фирме Userland. Название протокола - "Простой протокол доступа к объектам" - отражает его первоначальное назначение - обращаться к методам удаленных объектов. Назначение протокола изменилось, сейчас это протокол всякого взаимодействия Web-служб и компонентов слабо связанных распределенных приложений. Он уже не совсем прост, да и об объектах он ничего не говорит. Многие разработчики предлагают назвать его "Service Oriented Architecture Protocol", оставив прежнее сокращение. Чтобы прекратить эти попытки, в спецификации SOAP 1.2 указано, что слово "SOAP" отныне никак не будет расшифровываться.

В конце 1999 года разработка протокола была передана в консорциум W3C (http: //www.w3.org/ ).

В мае 2000 года консорциум выпустил свою версию SOAP 1.1. Послание, написанное по протоколу SOAP, оформляется документом XML, активно использующим пространства имен. Имена элементов XML версии SOAP 1.1 относятся к пространству имен с идентификатором http://schemas.xmlsoap.org/soap/envelope/.

Черновик второй версии SOAP 1.2 был выпущен в 2001 году, его пространство имен называлось в то время http://www.w3.org/2001/06/soap-envelope.

Заметьте, что именно идентификатор пространства имен, а не номер 1.1 или 1.2 определяет версию SOAP. Сервер не станет рассматривать SOAP- послание и вернет сообщение об ошибке если заметит

несоответствие пространства имен.

В то время как я пишу эти строки, версия SOAP 1.1 остается рабочей. Версия 1.2 никак не может выйти из подготовительной стадии, но уже используется, например, в SOAP::Lite, Apache SOAP 2.3, Apache Axis. Поэтому в этой главе я буду излагать версию 1.2, отмечая ее отличия от версии 1.1.

Спецификация рабочей версии SOAP всегда хранится по адресу http://www.w3.org/TR/SOAP/. Документы, лежащие по этому адресу, заменяются новыми при замене рабочей версии.

Черновая версия SOAP постоянно обновляется, при этом меняется идентификатор пространства имен. Новейший вариант черновой версии на время написания книги хранился по адресу http://www.w3.org/TR/soapl2-partl/, а пространство используемых ею имен называлось http://www.w3.org/2002/06/soap-envelope. Заметьте, что спецификация SOAP 12 состоит из двух частей: part 1 и part2. Вторая часть спецификации - приложение - содержит правила записи сложных типов данных. У спецификации есть еще одна часть partO - примеры посланий, составленных по правилам SOAP 1.2.

Структура SOAP-послания

Спецификация определяет SOAP-послание как документ XML, не содержащий объявление типа документа и инструкций по обработке. Корневой элемент этого документа XML называется . У элемента могут быть атрибуты определяющие пространства имен,

и другие атрибуты, снабженные префиксами. В корневой элемент вкладывается один необязательный элемент содержащий заголовок послания, и один обязательный элемент , в который записывается содержимое послания. Версия 1.1 позволяла после тела записать произвольные элементы, их имена обязательно следовало снабжать префиксами. Версия 1.2 запрещает писать что-либо после элемента . Короче говоря, общая структура SOAP-послания такова:

xmlns:env="http://www.w3.org/2002/06/soap-envelope">

< ! - Блоки заголовка ->

Элемент

, если он есть в послании, записывается первым в теле элемента . Кроме атрибутов xmlns, в нем может быть атрибут actor, указывающий адресом URI конкретный SOAP-сервер, которому предназначено послание.

Дело в том, что SOAP-послание может пройти через несколько SOAP- серверов или через несколько приложений на одном сервере. Эти приложения выполняют предварительную обработку блоков заголовка послания и передают его друг другу. Все эти серверы и/или приложения называются SOAP-узлами (SOAP nodes). Спецификация SOAP не определяет правила прохождения послания по цепочке серверов. Для этого разрабатываются другие протоколы, например, Microsoft WS-Routing.

Атрибут actor задает целевой SOAP-узел - тот, который расположен в конце цепочки и будет обрабатывать заголовок полностью. Значение

атрибута actor показывает, что обрабатывать заголовок будет первый же сервер, получивший Атрибут actor может встречаться в отдельных блоках заголовка, указывая узел- обработчик этого блока. После обработки блок удаляется из SOAP- послания.

В версии 1.2 атрибут actor заменен атрибутом role, потому что в этой версии SOAP каждый узел играет одну или несколько ролей. Спецификация пока определяет три роли SOAP-узла.

Роль http://^^.w3.org/2002/06/soap-envelope/role/ultimateReceiver играет конечный, целевой узел, который будет обрабатывать заголовок.

Роль http://www.w3.org/2002/06/soap-envelope/role/next играет промежуточный или целевой узел. Такой узел может играть и другие, дополнительные роли.

Роль http://www.w3.org/2002/06/soap-envelope/role/none не должен играть ни один SOAP-узел.

Распределенные приложения, исходя из своих нужд, могут добавить к этим ролям другие роли, например, ввести промежуточный сервер, проверяющий цифровую подпись и определить для него эту роль какой-нибудь строкой URI.

Значением атрибута role может быть любая строка URI, показывающая роль узла, которому предназначен данный блок заголовка. Значением по умолчанию для этого атрибута служит пустое значение, то есть, просто пара кавычек, или строка URI http://\vw\v.w3.org/2002/06/soap-envelope/rale/ultimateReceiver.

Значение атрибута role показывает, что блок должен быть обработан узлом, играющим роль, определенную такой же строкой.

Еще один атрибут элемента

, называемый urnstUnderstand, принимает значения о или 1. Его значение по умолчанию равно о. Если атрибут mustunderstand равен 1, то SOAP-узел при обработке элемента обязательно должен учитывать его синтаксис, определенный в схеме документа, или совсем не обрабатывать послание. Это повышает точность обработки послания.

В версии SOAP 1.2 вместо цифры о надо писать слово false, а вместо цифры 1 писать слово true.

В тело заголовка

можно вложить произвольные элементы, ранее называвшиеся статьями (entries) заголовка. В версии 1.2 они называются блоками (blocks) заголовка. Их имена обязательно помечаются префиксами. В блоках заголовка могут встретиться атрибуты role или actor и mustunderstand. Их действие будет относиться только к данному блоку. Это позволяет обрабатывать отдельные блоки заголовка промежуточными SOAP- узлами, теми, чья роль совпадает с ролью, указанной атрибутом role. В листинге 3.1 приведен пример такого блока.

Листинг 3.1. Заголовок с одним блоком

xmlns:t="http://some.com/transaction" env:role=

"http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver" env:mustUnderstand="1">

Элементы, вложенные в блоки заголовка, уже не называются блоками. Они не могут содержать атрибуты role, actor И mustunderstand.

Элемент обязательно записывается сразу за элементом

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

Сообщение об ошибке

Если SOAP-сервер, обрабатывая поступившее к нему SOAP-послание, заметит ошибку, то он прекратит обработку и отправит клиенту SOAP- послание, в тело которого запишет один элемент с сообщением об ошибке.

В сообщении, записанном в теле элемента версии SOAP 1.1 выде

ляются четыре части, описанные следующими вложенными элементами.

Код ошибки - сообщение, показывающее тип ошибки. Оно предназначено для программы, обрабатывающей ошибки.

Описание ошибки - словесное описание типа ошибки, предназначенное для человека.

Место обнаружения ошибки - адрес URI сервера, заметившего ошибку. Полезно, когда послание проходит цепочку SOAP- узлов, для уточнения природы ошибки. Промежуточные SOAP-узлы обязательно записывают этот элемент, целевой SOAP-сервер не обязан это делать.

Детали ошибки - описывают ошибки, встреченные в теле послания, но не в его заголовке. Если при обработке тела ошибки не обнаружены, то этот элемент отсутствует.

Например:

xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">

env:MustUnderstand SOAP Must Understand Error

Версия SOAP 1.2 изменила содержание элемента Как описано в

пространстве имен http://www.w3.org/2002/06/soap-envelope, в него входят два обязательных элемента и три необязательных элемента.

Обязательные элементы.

Код ошибки . Он содержит обязательный вложенный элемент <:value> с кодом ошибки и необязательный вложенный элемент , содержащий, опять-таки, элемент с уточняющим кодом ошибки и элемент , и далее все повторяется рекурсивно.

Причина ошибки . Содержит необязательный атрибут xml: lang, указывающий язык сообщения (см. главу Г), и произвольное число вложенных элементов с описанием ошибки.

Необязательные элементы.

? - адрес URI промежуточного SOAP-узла, заметившего ошибку.

? - роль SOAP-узла, заметившего ошибку.

? - описание ошибки, замеченной при обработке тела послания, но не заголовка.

Листинг 3.2 показывает сообщение об ошибке, возникшей при попытке выполнения процедуры. Ошибка заключается в том, что имена аргументов процедуры неправильно записаны в SOAP-послании и процедура не может их понять.

Листинг 3.2. Сообщение об ошибке

xmlns:env="http://www.w3.org/2002/06/soap-envelope" xmlns:rpc=’http://www.w3.org/2002/06/soap-rpc’>

env:Sender

rpc:BadArgumentsc/env:Value>

Ptocessing ETror

xmlns:e="http://www.example.org/faults"> №me does not match 999

Типы ошибок

Список кодов ошибок постоянно меняется и расширяется. Версия 1.1 определяет четыре типа ошибок.

VersionMismatch - пространство имен неопознано. Может быть, оно устарело или его имя написано неправильно.

MustUnderstand - блок заголовка, помеченный атрибутом mustUnderstand со значением 1, не отвечает своему синтаксису, определенному в схеме документа.

Client - документ XML, содержащий послание, неправильно сформирован и по этой причине сервер не может его обработать. Клиенту следует изменить послание.

Server - сервер не может обработать правильно записанное послание по своим внутренним причинам.

Версия 1.2 определяет пять типов ошибок.

VersionMismatch - пространство имен неопознано. Может быть, оно устарело или его название написано неправильно, или в послании встретилось имя элемента XML, не определенное в этом пространстве имен. В заголовок ответа сервер записывает элемент , перечисляющий вложенными элементами правильные названия пространств имен, понимаемые сервером. Ответ сервера показан в листинге 3.3.

MustUnderstand - блок заголовка, помеченный атрибутом mustunderstand со значением true, не отвечает своему синтаксису, определенному в схеме документа. Сервер записывает в заголовок ответа элементы , атрибут qname которых содержит имя неправильного блока. Листинг 3.4 содержит пример ответа, который будет сделан сервером, если заголовок листинга 3.1 окажется неправильно записанным.

DataEncodingUnknown - в послании встретились непонятные данные, может быть, они записаны в неизвестной кодировке.

Sender - документ XML, содержащий послание, неправильно сформирован и по этой причине сервер не может его обработать. Клиенту следует изменить послание.

Receiver - сервер не может обработать правильно записанное послание по своим внутренним причинам, например, отсутствует нужный XML- парсер.

Сервер может добавить к этим типам ошибок какие-то свои типы. Обычно

они детализируют стандартные типы, и сообщения о них появляются в элементах , как было показано выше в листинге 3.2.

? Листинг 3.3. Ответ сервера с сообщением об ошибке типа VersionMismatch

xmlns:env="http://www.w3.org/2002/06/soap-envelope">

xmlns:upg="http://www.w3.org/2002/06/soap-upgrade">

xmlns:nsl="http://www.w3.org/2002/06/soap-envelope"/>

xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/"/>

env:VersionMismatch

Version Mismatch

ЛистонгЗ.4. Ответ сервера с сообщением об ошибке типа MustUnderstand

xmlns:t=’http://some.com/transaction’ />

env:MustUnderstand

One or more mandatory headers not understood

Литература:

Хабибуллин И. Ш. Разработка Web-служб средствами Java. - СПб.: БХВ-Петербург, 2003. - 400 с: ил.