Веб-сервис
Давайте сначала поговорим о веб-сервисе. Что такое веб-сервис Люди склонны говорить, что веб-сервис — это не более, чем процесс удаленного вызова метода (RMI). На самом деле, речь идет не только о RMI. Веб-сервис представляет собой набор конечных точек (или одной конечной точки), предоставляемых по протоколу HTTP. Для связи с этими конечными точками нам необходимо создать клиентов для доступа к конечным точкам. Самое большое преимущество такого вида связи между конечной точкой веб-службы и клиентом заключается в том, что это определяется протоколом SOAP , основанным на протоколе HTTP (или иногда даже протоколом SMTP).
Этот протокол определяет структуру данных, которые передаются между конечной точкой и клиентом. Данные обмениваются в формате XML. Как следствие, веб-сервис не зависит от платформы / технологии. Например, веб-сервис может быть реализован с использованием инфраструктуры Java CXF или простых веб-служб JBoss. Клиент, который обращается к этому веб-сервису, может быть реализован, скажем, не в среде Java. Технология веб-службы и технология клиента могут быть совершенно разными, и связь между ними все еще возможна, поскольку протокол SOAP основан на формате сообщений XML. Единственное, что требуется для успешного взаимодействия, это то, что и конечная точка, и клиент согласовывают, как должно выглядеть XML-сообщение (какие поля и какой тип содержимого будут присутствовать в XML-файле) и какие операции ( методы), который клиент может вызвать в конечной точке.
Эти требования определены WSDL. WSDL (язык описания веб-сервисов) — это язык на основе XML, который используется для описания конечных точек веб-сервиса. Он может определить HTTP-адрес конечной точки, операции, которые могут быть выполнены клиентом в этой конечной точке, тип данных, которые могут быть переданы операциям, и какой тип данных получен обратно из этих операций конечных точек. Он также определяет точную структуру сообщений XML, которые используются в связи с конечной точкой. Информация такого рода обычно хранится в файле с расширением wsdl. Так появился в мире известный термин «файл wsdl».
Хорошо, этого достаточно для веб-сервисов. На самом деле, я мог бы много написать о веб-сервисах и протоколе SOAP, но это было бы за рамками этого блога. Вам предлагается сделать это самостоятельно. В интернете есть множество статей на эту тему.
Создание простого веб-сервиса на JBoss
Пример, который я собираюсь показать вам, находится в затмении 3.7 (индиго), и я буду использовать JBoss 4.2.3.GA в качестве сервера. В качестве инструмента для сборки проекта я буду использовать maven. Давайте начнем с создания самого простого веб-проекта в Eclipse. Он будет содержать реализацию веб-сервисов (конечная точка).
Это просто проект maven для обычного веб-приложения. Ничего особенного. Если вы не хотите использовать Maven, это тоже хорошо. Вы можете использовать любой инструмент для создания простого веб-приложения.
Здесь я не буду вдаваться в подробности о том, как создать этот простой проект. Вместо этого я предоставлю вам снимок экрана со структурой проекта в моем затмении.
Структура проекта в затмении. |
Теперь давайте создадим веб-сервис. Мы сделаем « восходящий подход ». Это означает, что мы сначала разработаем класс реализации, а позже определим WSDL. Итак, давайте напишем простой Java-класс POJO. Мы просто притворимся, что наш веб-сервис принимает какой-то идентификатор автомобиля в качестве параметра и возвращает цену за этот автомобиль. Если мы передадим несуществующий идентификатор автомобиля, то веб-сервис вернет соответствующий текст ошибки.
Основными элементами, которые здесь нужно увидеть, являются интерфейс CarWebService и класс CarWebServiceImpl, который фактически реализует интерфейс конечной точки.
Начнем с интерфейса CarWebService . Вот код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
package ba.codecentric.webservice; import javax.jws.WebMethod; import javax.jws.WebService; import ba.codecentric.webservice.model.CarResponse; @WebService public interface CarWebService { @WebMethod public CarResponse getCarPrice(String carId); } |
Как видите, это нормальное определение интерфейса. Здесь следует отметить только две вещи: две аннотации: @WebService и @WebMethod . Эти аннотации относятся к области технологии под названием JAX-WS. JAX-WS — это спецификация о том, как создавать веб-сервисы и клиенты таким образом, чтобы они могли взаимодействовать с вызовами RPC и обмениваться сообщениями на основе XML. Java имеет собственную реализацию JAX-WS и позволяет нам определять конечную точку веб-службы с помощью этих простых аннотаций. Вы можете прочитать больше о JAX-WS здесь . Внутренне эта технология в Java имеет дело с получением и анализом XML-сообщений (обычно обмениваются протоколом SOAP). Это защищает разработчика от многих часов кропотливой работы, поэтому разработчику не нужно тратить время на написание кода для создания мыльного сообщения, его отправки, затем получения на стороне сервера, извлечения информации из xml и т. Д. Все это сделано внутренне механизмом JAX-WS в Java.
Поэтому, когда вы хотите создать конечную точку простого Java-сервиса на сервере, вы просто создаете интерфейс. Пометьте интерфейс аннотацией WebService и отметьте все методы в интерфейсе, которые вы хотите представить как удаленные (с аннотацией WebMethod). Затем они станут операциями, которые могут быть вызваны на интерфейсе. В моем примере у меня есть только один метод, но может быть гораздо больше.
Следующая остановка — создание реализации интерфейса. Мы разоблачили методы веб-службы (операции конечной точки). Эти методы должны что-то делать, чтобы веб-сервис имел смысл. В Java мы делаем это действительно просто. Мы просто создадим класс реализации для интерфейса.
Я покажу вам код для CarWebServiceImpl.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package ba.codecentric.webservice.impl; import java.util.HashMap; import java.util.Map; import javax.jws.WebService; import ba.codecentric.webservice.CarWebService; import ba.codecentric.webservice.model.CarResponse; @WebService (endpointInterface = 'ba.codecentric.webservice.CarWebService' ) public class CarWebServiceImpl implements CarWebService { private final Map<String, Integer> prices = new HashMap<String, Integer>(); public CarWebServiceImpl() { prices.put( 'audi' , Integer.valueOf( 10000 )); prices.put( 'bmw' , Integer.valueOf( 15000 )); prices.put( 'fiat' , Integer.valueOf( 5000 )); } public CarResponse getCarPrice(String carId) { Integer price = prices.get(carId); CarResponse response = new CarResponse(); if (price == null ) { response.setCarPrice(- 1 ); response.setStatus( 'error: no car with id: ' + carId); } else { response.setCarPrice(price.intValue()); response.setStatus( 'ok' ); } return response; } } |
Единственное, что следует заметить, это специальная аннотация. То же, что и в интерфейсе, но у него есть только один дополнительный аргумент. Это полное имя интерфейса конечной точки. Ничего больше.
В реальном мире этот веб-сервис мог бы иметь более сложный код. Это заняло бы какой-то идентификатор автомобиля, а затем было бы искать машину в базе данных. Но здесь я сделал намного проще. У меня есть карта для трех разных идентификаторов автомобилей, и там хранятся цены с идентификаторами.
Если вы передадите существующий идентификатор автомобиля службе (например, audi, bmw), вы получите ответ от веб-службы на сервере. Ответ будет содержать статусное сообщение (в порядке) и цену автомобиля.
Если вы передадите в сервис несуществующий идентификатор автомобиля, вы получите ответ с ошибкой статуса, а также у вас будет подробная строка, сообщающая, что искомый автомобиль не был найден. Цена автомобиля в этом случае будет установлена на -1.
ОК. Вот и все, что касается реализации веб-сервиса. Просто, не правда ли? Осталось сделать еще одну вещь. А этот еще проще. Вам нужно представить класс реализации как сервлет. Вы сделаете это в web.xml . Вот код:
1
2
3
4
5
6
7
8
9
|
< servlet > < servlet-name >carWebservice</ servlet-name > < servlet-class >ba.codecentric.webservice.impl.CarWebServiceImpl</ servlet-class > </ servlet > < servlet-mapping > < servlet-name >carWebservice</ servlet-name > < url-pattern >/ws/car</ url-pattern > </ servlet-mapping > |
И мы сделали. Теперь нам нужно упаковать приложение и развернуть его в JBoss.
JBoss позаботится о том, чтобы опубликовать эту конечную точку для вас, поэтому вам не нужно беспокоиться об этом.
Так что давай. Разверните ваше приложение в JBoss. Если вы используете maven в качестве инструмента для сборки, вот как должен выглядеть ваш pom.xml :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
< build > < finalname >webservices</ finalName > < plugins > < plugin > < groupid >org.apache.maven.plugins</ groupId > < artifactid >maven-compiler-plugin</ artifactId > < version >2.5.1</ version > < configuration > < source >1.6</ source > < target >1.6</ target > </ configuration > </ plugin > </ plugins > </ build > |
Установите исходную и целевую версии для компилятора maven на java 6 из-за использования аннотаций.
JBoss имеет свое небольшое веб-приложение, которое позволяет вам видеть все веб-сервисы, которые развернуты в настоящее время, и расположение всех файлов WSDL для этих веб-сервисов.
Вы можете получить доступ к этому небольшому приложению по этому адресу: http: // localhost: 8080 / jbossws / services
Конечно, при условии, что ваше имя сервера JBoss — localhost, а его http-порт настроен на 8080.
Вот снимок экрана с моего компьютера, который ясно показывает, что веб-службы, которые мы развернули в этом примере, действительно работают.
Вы можете нажать на ссылку конечной точки. В результате вы увидите WSDL конечной точки. Внутри этого WSDL вы увидите что-то вроде <import location = ‘……’> . Значением атрибута location является реальный URL полного WSDL. Так что давай. Также откройте этот URL в браузере. Теперь вы должны увидеть весь WSDL (определения конечных точек, операции, которые могут быть вызваны, сообщения, отправленные на конечные точки и полученные обратно от конечных точек). Я надеюсь, что это облегчает понимание того, как на самом деле веб-службы обмениваются данными с клиентами. Клиент просто создает запрос на основе файла WSDL, который он получает от веб-службы. В этом файле WSDL клиент может видеть все, что необходимо для связи с конечной точкой. Все остальное обеспечивается протоколом SOAP и механизмом Java JAX-WS. Разработчик не должен видеть, что одна из этих операций вызывается.
Создание простого клиента веб-сервиса (утилита wsconsume)
Чтобы вызвать этот веб-сервис, нам нужно создать клиента. Клиент может быть простым консольным приложением Java. Это даже не должно быть веб-приложение, если вы не хотите усложнять вещи. это означает, что вы можете иметь простой класс Java с методом main () . И все, что вам нужно, это несколько строк кода, и все готово. Первое, что нам нужно сделать здесь, это сгенерировать так называемые «классы-заглушки». Эти классы представляют классы запросов и ответов моделей, которые мы используем для связи с веб-сервисом. Если вы помните, я создал специальный класс-обертку для возврата ответа веб-службы. Но это не только классы моделей, которые находятся в этих классах-заглушках. Здесь вы также найдете классы, которые фактически выполняют вызов удаленной конечной точки и некоторые другие служебные классы. Также вы найдете некоторые аннотации JAXB, которые необходимы при маршалинге и демаршалировании java-объектов в XML-сообщения, а также наоборот. Эти классы-заглушки создаются на основе файла WSDL конечной точки. Если вы помните, файл WSDL содержит всю информацию, которая нужна клиенту. На основе файла WSDL мы можем сгенерировать все необходимые классы-заглушки (классы моделей, используемые для связи с веб-сервисом, и служебные классы, которые используются для облегчения этого взаимодействия). К счастью для нас, у JBoss есть небольшая служебная программа, которую мы будем использовать для генерации этих классов. Нам не нужно писать ни одной строки кода для этих классов-заглушек. И мы также можем сказать этому инструменту генерировать классы непосредственно в нашей рабочей области. Действительно классные вещи. Итак, давайте попробуем. Инструмент называется wsconsume.bat и находится в папке JBoss — bin. для пользователей Linux есть wsconsume.sh .
Сначала я создам другой проект для этого в Eclipse. Я назову это ws-client . Это обычный проект Java. Вы можете просто выбрать File -> New -> Java Project и использовать все настройки по умолчанию. ОК. Теперь мы готовы к созданию классов-заглушек. Мы хотим, чтобы утилита wsconsume немедленно помещала классы в папку src для исходных файлов java. И мы также сообщим утилите wsconsume точное имя пакета, который она должна использовать для этих классов. Мой проект находится здесь: D: \ JBossTests \ jbossWebServiceWorkspace \ ws-client .
Таким образом, команда для wsconsume utlity должна быть такой: D: \ JBossTests \ jboss-4.2.3.GA \ bin> wsconsume -v -k -p ws.client.impl -s D: \ JBossTests \ jbossWebServiceWorkspace \ ws-client \ ЦСИ
http://127.0.0.1:8080/webservices/ws/car?wsdl
Убедитесь, что вы выполняете эту команду из папки jboss bin. В противном случае убедитесь, что на вашем пути есть файл wsconsume.bat для доступа к нему из любой папки.
Также убедитесь, что ваш jboss работает и веб-службы, для которых вы пытаетесь сгенерировать клиент, правильно развернуты и работают.
Давайте объясним параметры, которые я использовал здесь:
-v: подробный (показать полную трассировку стека ошибок при наличии ошибки);
-k: сохранять / генерировать исходники java;
-p: имя пакета. Сгенерированные классы сразу получат данный пакет;
-s: исходная папка. Каталог, куда поместить исходные файлы. Я использовал исходную папку моего клиентского проекта, что имеет смысл.
И, наконец, у нас есть URL-адрес местоположения конечной точки WSDL.
Вы можете открыть URL-адрес jboss http: // localhost: 8080 / jbossws / services, чтобы просмотреть все развернутые веб-службы и просмотреть все URL-адреса WSDL. Вы можете просто скопировать / вставить требуемый URL-адрес WSDL в командную строку для утилиты wsconsume . В нашем случае это местоположение веб-сервиса, который мы создали ранее.
Теперь перейдите к eclipse и обновите вашу папку src в новом клиентском проекте. Теперь у вас должно быть несколько классов, сгенерированных утилитой wsconsume, и они должны быть в указанном пакете. Все, что нам нужно сделать сейчас, это запустить этот клиент и отправить запросы веб-сервисам. Просто создайте еще один класс. Я назову это CarWebserviceClient . И я положу его в отдельный пакет. И этот класс будет иметь обычный метод Java. Пакет является ws.client.runner :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package ws.client.runner; import ws.client.impl.CarResponse; import ws.client.impl.CarWebService; import ws.client.impl.CarWebServiceImplService; public class CarrWebserviceClient { public static void main(String[] args) { CarWebServiceImplService service = new CarWebServiceImplService(); CarWebService port = service.getCarWebServiceImplPort(); CarResponse audiPrice = port.getCarPrice( 'audi' ); System.out.println( 'audi price: ' + audiPrice.getCarPrice() + ' EUR; web service status: ' + audiPrice.getStatus()); CarResponse fordPrice = port.getCarPrice( 'ford' ); System.out.println( 'ford price: ' + fordPrice.getCarPrice() + ' EUR; web service status: ' + fordPrice.getStatus()); } } |
Как вы видите этот код выше очень прост. Вам просто нужно создать экземпляр клиента, затем получить порт для службы и все. Мы можем вызвать операцию веб-службы, вызвав метод java с тем же именем. Просто передайте параметры, которые вы хотите. Вы можете использовать audi , bmw и fiat как жестко закодированные существующие значения. Вы также можете попытаться получить цену для некоторого несуществующего идентификатора автомобиля. Так же, как я пытался в примере выше.
Конечно, не забудьте запустить jboss и развернуть веб-сервисы, чтобы это работало 🙂
Ну, это было бы все. Это может быть хорошей отправной точкой для продолжения вашего путешествия в мир веб-сервисов на основе SOAP. Это был самый простой пример, реализованный с использованием API-интерфейса JAX-WS и небольшой помощи jboss для веб-сервисов.
Ссылка: Основные веб-службы Java на JBoss от нашего партнера по JCG Бранислава Видови? в блоге Geek 🙂 .